मैं वास्तव में नोड.जेएस का उपयोग करके HTML5 क्लाइंट के लिए ffmpeg के वास्तविक समय के उत्पादन को स्ट्रीम करने का सबसे अच्छा तरीका समझने की कोशिश कर रहा हूं, क्योंकि नाटक में कई चर हैं और मुझे इस स्थान का बहुत अनुभव नहीं है, विभिन्न संयोजनों की कोशिश में कई घंटे बिताए।
मेरा उपयोग मामला है:
1) IP वीडियो कैमरा RTSP H.264 स्ट्रीम FFMPEG द्वारा उठाया गया है और नोड में निम्नलिखित FFMPEG सेटिंग्स का उपयोग करके एक mp4 कंटेनर में रीमेक किया गया है, STDOUT को आउटपुट। यह केवल प्रारंभिक क्लाइंट कनेक्शन पर चलाया जाता है, ताकि आंशिक सामग्री अनुरोध फिर से FFMPEG को स्पॉन करने का प्रयास न करें।
liveFFMPEG = child_process.spawn("ffmpeg", [
"-i", "rtsp://admin:12345@192.168.1.234:554" , "-vcodec", "copy", "-f",
"mp4", "-reset_timestamps", "1", "-movflags", "frag_keyframe+empty_moov",
"-" // output to stdout
], {detached: false});
2) मैं STDOUT पर कब्जा करने और क्लाइंट अनुरोध पर क्लाइंट को वापस स्ट्रीम करने के लिए नोड http सर्वर का उपयोग करता हूं। जब क्लाइंट पहली बार कनेक्ट होता है तो मैं ऊपर FFMPEG कमांड लाइन को स्पॉन करता हूं फिर HTTP प्रतिक्रिया के लिए STDOUT स्ट्रीम को पाइप करता है।
liveFFMPEG.stdout.pipe(resp);
मैंने FFMPEG डेटा को HTTP प्रतिसाद लिखने के लिए स्ट्रीम इवेंट का भी उपयोग किया है, लेकिन कोई फर्क नहीं पड़ता
xliveFFMPEG.stdout.on("data",function(data) {
resp.write(data);
}
मैं निम्नलिखित HTTP हेडर का उपयोग करता हूं (जो पूर्व-रिकॉर्ड की गई फ़ाइलों को स्ट्रीमिंग करते समय भी उपयोग किया जाता है और काम करता है)
var total = 999999999 // fake a large file
var partialstart = 0
var partialend = total - 1
if (range !== undefined) {
var parts = range.replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
}
var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : total; // fake a large file if no range reques
var chunksize = (end-start)+1;
resp.writeHead(206, {
'Transfer-Encoding': 'chunked'
, 'Content-Type': 'video/mp4'
, 'Content-Length': chunksize // large size to fake a file
, 'Accept-Ranges': 'bytes ' + start + "-" + end + "/" + total
});
3) क्लाइंट को HTML5 वीडियो टैग का उपयोग करना होगा।
HTML5 क्लाइंट को उपरोक्त FFMPEG कमांड लाइन के साथ रिकॉर्ड की गई एक वीडियो फ़ाइल (लेकिन STDOUT के बजाय एक फ़ाइल में सहेजी गई) के साथ प्लेबैक प्लेबैक (206 HTTP आंशिक सामग्री के साथ fs.createReadStream का उपयोग करने) के साथ मुझे कोई समस्या नहीं है, इसलिए मुझे FFMPEG स्ट्रीम पता है सही है, और मैं HTTP नोड सर्वर से कनेक्ट होने पर वीएलसी में वीडियो लाइव स्ट्रीमिंग को भी सही ढंग से देख सकता हूं।
हालाँकि, FFMPEG से नोड HTTP के माध्यम से लाइव स्ट्रीम करने की कोशिश बहुत कठिन प्रतीत होती है क्योंकि क्लाइंट एक फ्रेम को प्रदर्शित करेगा फिर रुक जाएगा। मुझे संदेह है कि मैं HTML5 वीडियो क्लाइंट के साथ संगत होने के लिए HTTP कनेक्शन स्थापित नहीं कर रहा हूं। मैंने HTTP 206 (आंशिक सामग्री) और 200 प्रतिक्रियाओं का उपयोग करने, डेटा को बफर में डालने और फिर बिना किसी भाग्य के स्ट्रीमिंग जैसी कई चीजों की कोशिश की है, इसलिए मुझे यह सुनिश्चित करने के लिए पहले सिद्धांतों पर वापस जाने की आवश्यकता है कि मैं यह अधिकार स्थापित कर रहा हूं। मार्ग।
यहाँ मेरी समझ है कि यह कैसे काम करना चाहिए, कृपया मुझे सही करें अगर मैं गलत हूँ:
1) FFMPEG को आउटपुट के टुकड़े करने के लिए सेटअप किया जाना चाहिए और एक खाली moov (FFMPEG frag_keyframe और blank_moov mov ध्वज) का उपयोग करना चाहिए। इसका मतलब यह है कि ग्राहक मूव एटम का उपयोग नहीं करता है जो आम तौर पर फाइल के अंत में होता है जो स्ट्रीमिंग के दौरान प्रासंगिक नहीं होता है (फाइल का कोई अंत नहीं है), लेकिन इसका मतलब यह है कि संभव नहीं है जो मेरे उपयोग के मामले के लिए ठीक है।
2) भले ही मैं MP4 अंशों और रिक्त MOOV का उपयोग करता हूं, फिर भी मुझे HTTP आंशिक सामग्री का उपयोग करना होगा, क्योंकि HTML5 खिलाड़ी प्रतीक्षा करेगा जब तक कि पूरी स्ट्रीम को डाउनलोड करने से पहले डाउनलोड नहीं किया जाता है, जो कि लाइव स्ट्रीम के साथ कभी समाप्त नहीं होता है इसलिए यह अटूट है।
3) मुझे समझ में नहीं आता है कि HTTP प्रतिक्रिया के लिए STDOUT स्ट्रीम को पाइप करना क्यों काम नहीं करता है जब अभी तक लाइव स्ट्रीमिंग नहीं होती है अगर मैं किसी फ़ाइल को सहेजता हूं तो मैं समान कोड का उपयोग करके एचटीएमएल 5 क्लाइंट को इस फाइल को आसानी से स्ट्रीम कर सकता हूं। शायद यह एक टाइमिंग का मुद्दा है क्योंकि इसे शुरू करने के लिए एफएफएमपीजी स्पॉन के लिए एक दूसरा समय लगता है, आईपी कैमरा से कनेक्ट करना और नोड्स को भेजना और नोड डेटा इवेंट भी अनियमित हैं। हालाँकि बायस्ट्रीम बिलकुल फाइल में सेविंग की तरह ही होनी चाहिए, और HTTP को देरी के लिए पूरा करने में सक्षम होना चाहिए।
4) कैमरे से FFMPEG द्वारा बनाई गई MP4 फ़ाइल को स्ट्रीम करते समय HTTP क्लाइंट से नेटवर्क लॉग की जाँच करते समय, मुझे लगता है कि 3 क्लाइंट अनुरोध हैं: वीडियो के लिए एक सामान्य GET अनुरोध, जिसे HTTP सर्वर 40Kb के बारे में देता है, फिर एक आंशिक फ़ाइल के अंतिम 10K के लिए बाइट रेंज के साथ सामग्री अनुरोध, फिर बीच में बिट्स के लिए एक अंतिम अनुरोध लोड नहीं किया गया। हो सकता है कि HTML5 क्लाइंट एक बार पहली प्रतिक्रिया प्राप्त करता है जो MP4 MOOV परमाणु को लोड करने के लिए फ़ाइल के अंतिम भाग के लिए पूछ रहा है? यदि यह मामला है तो यह स्ट्रीमिंग के लिए काम नहीं करेगा क्योंकि कोई MOOV फ़ाइल नहीं है और फ़ाइल का कोई छोर नहीं है।
5) जब लाइव स्ट्रीम करने की कोशिश करते समय नेटवर्क लॉग की जाँच करते हैं, तो मुझे केवल 200 बाइट्स के साथ एक प्रारंभिक प्रारंभिक अनुरोध प्राप्त होता है, फिर 200 बाइट्स के साथ फिर से अनुरोध किया जाता है और तीसरा अनुरोध जो केवल 2K लंबा होता है। मुझे समझ में नहीं आता है कि HTML5 क्लाइंट अनुरोध को क्यों रद्द करेगा क्योंकि बाईटस्ट्रीम बिल्कुल वैसा ही है जैसा कि मैं किसी रिकॉर्ड की गई फ़ाइल से स्ट्रीमिंग के दौरान सफलतापूर्वक उपयोग कर सकता हूं। ऐसा भी लगता है कि नोड FFMPEG स्ट्रीम के बाकी क्लाइंट को नहीं भेज रहा है, फिर भी मैं .on ईवेंट रूटीन में FFMPEG डेटा देख सकता हूं इसलिए यह FFMPEG नोड HTTP सर्वर पर मिल रहा है।
6) हालांकि मुझे लगता है कि HTTP प्रतिक्रिया बफर को स्ट्रीम स्ट्रीम करने के लिए बफर काम करना चाहिए, क्या मुझे एक मध्यवर्ती बफर और स्ट्रीम का निर्माण करना है जो HTTP आंशिक सामग्री क्लाइंट अनुरोधों को ठीक से काम करने की अनुमति देगा जैसे यह (सफलतापूर्वक) एक फ़ाइल पढ़ता है ? मुझे लगता है कि यह मेरी समस्याओं का मुख्य कारण है लेकिन मैं निश्चित रूप से नोड में निश्चित नहीं हूं कि इसे कैसे सेट किया जाए। और मुझे नहीं पता कि फ़ाइल के अंत में डेटा के लिए क्लाइंट अनुरोध को कैसे संभालना है क्योंकि फ़ाइल का कोई अंत नहीं है।
) क्या मैं २०६ आंशिक सामग्री अनुरोधों को संभालने की कोशिश के साथ गलत रास्ते पर हूँ, और यह २०० HTTP की सामान्य प्रतिक्रियाओं के साथ काम करना चाहिए? HTTP 200 प्रतिक्रियाएं VLC के लिए ठीक काम करती हैं इसलिए मुझे संदेह है कि HTML5 वीडियो क्लाइंट केवल आंशिक सामग्री अनुरोधों के साथ काम करेगा?
जैसा कि मैं अभी भी इस समस्या (FFMPEG, नोड, स्ट्रीमिंग, HTTP, एचटीएमएल 5 वीडियो) की विभिन्न परतों के माध्यम से काम करना मुश्किल सीख रहा हूं, इसलिए किसी भी संकेत की बहुत सराहना की जाएगी। मैंने इस साइट और नेट पर शोध करते हुए घंटों बिताए हैं, और मैं किसी ऐसे व्यक्ति के साथ नहीं आया हूं जो नोड में वास्तविक समय स्ट्रीमिंग करने में सक्षम है, लेकिन मैं पहले नहीं हो सकता, और मुझे लगता है कि यह काम करने में सक्षम होना चाहिए (किसी तरह !)।
Content-Type
अपने सिर में सेट किया ? क्या आप चंक एन्कोडिंग का उपयोग कर रहे हैं? यहीं से शुरुआत करूंगा। इसके अलावा, एचटीएमएल 5 आवश्यक रूप से स्ट्रीम को कार्यक्षमता प्रदान नहीं करता है, आप यहां पर अधिक पढ़ सकते हैं । आपको अपने स्वयं के साधनों ( यहां देखें ) का उपयोग करके वीडियो स्ट्रीम को बफ़र करने और चलाने के लिए सबसे अधिक संभावना होगी , सोचा कि यह अच्छी तरह से समर्थित नहीं है। इसके अलावा MediaSource API में google।