วิธีที่ดีที่สุดในการสตรีม HTTP แบบเรียลไทม์ไปยังไคลเอนต์วิดีโอ HTML5


213

ฉันพยายามอย่างยิ่งที่จะเข้าใจวิธีที่ดีที่สุดในการส่งกระแสข้อมูลเรียลไทม์ของ ffmpeg ไปยังไคลเอนต์ HTML5 โดยใช้ node.js เนื่องจากมีจำนวนของตัวแปรที่เล่นและฉันไม่ได้มีประสบการณ์มากมายในพื้นที่นี้ ต้องใช้เวลาหลายชั่วโมงในการลองชุดค่าผสมที่แตกต่างกัน

กรณีใช้ของฉันคือ:

1) กล้องวิดีโอ IP IP สตรีม RTSP H.264 ถูกหยิบขึ้นมาโดย FFMPEG และนำกลับเข้าไปในคอนเทนเนอร์ mp4 โดยใช้การตั้งค่า FFMPEG ต่อไปนี้ในโหนดส่งออกไปยัง 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) ฉันใช้เซิร์ฟเวอร์ http http เพื่อจับ STDOUT และสตรีมที่กลับไปยังไคลเอนต์ตามคำขอของลูกค้า เมื่อไคลเอนต์แรกเชื่อมต่อฉันวางไข่บรรทัดคำสั่ง FFMPEG ข้างต้นแล้วไพพ์สตรีม STDOUT ไปยังการตอบสนอง HTTP

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

ฉันไม่มีปัญหากับการเล่นแบบสตรีมมิ่ง (ใช้ fs.createReadStream with 206 HTTP เนื้อหาบางส่วน) ไปยังไคลเอนต์ HTML5 ไฟล์วิดีโอที่บันทึกไว้ก่อนหน้านี้ด้วยบรรทัดคำสั่ง FFMPEG ข้างต้น (แต่บันทึกเป็นไฟล์แทน STDOUT) ดังนั้นฉันจึงรู้ FFMPEG สตรีม ถูกต้องและฉันยังสามารถดูสตรีมมิ่งวิดีโอสดใน VLC ได้อย่างถูกต้องเมื่อเชื่อมต่อกับเซิร์ฟเวอร์โหนด HTTP

อย่างไรก็ตามการพยายามสตรีมสดจาก FFMPEG ผ่านทางโหนด HTTP ดูเหมือนว่าจะยากขึ้นมากเนื่องจากไคลเอนต์จะแสดงหนึ่งเฟรมจากนั้นหยุด ฉันสงสัยว่าปัญหาคือฉันไม่ได้ตั้งค่าการเชื่อมต่อ HTTP ให้เข้ากันได้กับไคลเอนต์วิดีโอ HTML5 ฉันได้ลองทำสิ่งต่าง ๆ เช่นการใช้ HTTP 206 (เนื้อหาบางส่วน) และการตอบสนอง 200 ครั้งการใส่ข้อมูลลงในบัฟเฟอร์จากนั้นสตรีมมิ่งโดยไม่มีโชคดังนั้นฉันต้องย้อนกลับไปที่หลักการแรกเพื่อให้แน่ใจว่าฉันตั้งค่าถูกต้องแล้ว ทาง

นี่คือความเข้าใจของฉันเกี่ยวกับวิธีการทำงานนี้โปรดแก้ไขฉันหากฉันผิด:

1) FFMPEG ควรตั้งค่าให้แฟรกเมนต์เอาต์พุตและใช้ moov ว่างเปล่า (แฟล็ก FFMPEG Frag_keyframe และค่าสถานะ mov mov_moov) ซึ่งหมายความว่าลูกค้าไม่ได้ใช้ moov atom ซึ่งโดยทั่วไปแล้วจะอยู่ที่ท้ายไฟล์ซึ่งไม่เกี่ยวข้องเมื่อทำการสตรีม (ไม่สิ้นสุดไฟล์) แต่หมายถึงไม่สามารถค้นหาสิ่งที่เป็นไปได้ซึ่งเหมาะสำหรับเคสการใช้งานของฉัน

2) แม้ว่าฉันจะใช้ชิ้นส่วน MP4 และ MOOV ที่ว่างเปล่าฉันยังคงต้องใช้เนื้อหา HTTP บางส่วนเนื่องจากผู้เล่น HTML5 จะรอจนกว่าจะดาวน์โหลดสตรีมทั้งหมดก่อนที่จะเล่นซึ่งการสตรีมสดจะไม่สิ้นสุด

3) ฉันไม่เข้าใจว่าทำไมการไพพ์สตรีม STDOUT ไปยังการตอบสนอง HTTP ไม่ทำงานเมื่อสตรีมมิงแบบสด แต่ถ้าฉันบันทึกเป็นไฟล์ฉันสามารถสตรีมไฟล์นี้ไปยังไคลเอนต์ HTML5 ได้อย่างง่ายดายโดยใช้รหัสที่คล้ายกัน อาจเป็นปัญหาเกี่ยวกับเวลาเนื่องจากใช้เวลาวินาทีสำหรับ FFMPEG วางไข่เริ่มต้นเชื่อมต่อกับกล้อง IP และส่งชิ้นไปยังโหนดและเหตุการณ์ข้อมูลโหนดก็ผิดปกติเช่นกัน อย่างไรก็ตาม bytestream ควรเหมือนกับการบันทึกไฟล์และ HTTP ควรจะรองรับความล่าช้าได้

4) เมื่อตรวจสอบบันทึกเครือข่ายจากไคลเอนต์ HTTP เมื่อสตรีมไฟล์ MP4 ที่สร้างโดย FFMPEG จากกล้องฉันเห็นว่ามีคำขอไคลเอนต์ 3 คำขอ: คำขอ GET ทั่วไปสำหรับวิดีโอซึ่งเซิร์ฟเวอร์ HTTP ส่งคืนประมาณ 40Kb จากนั้นบางส่วน คำขอเนื้อหาที่มีช่วงไบต์สำหรับ 10K สุดท้ายของไฟล์จากนั้นคำขอสุดท้ายสำหรับบิตที่อยู่ตรงกลางจะไม่โหลด บางทีไคลเอนต์ HTML5 เมื่อได้รับการตอบกลับครั้งแรกขอให้ส่วนสุดท้ายของไฟล์โหลด atom MOOV MP4 หรือไม่ หากเป็นกรณีนี้มันจะไม่ทำงานสำหรับการสตรีมเนื่องจากไม่มีไฟล์ MOOV และไม่มีจุดสิ้นสุดไฟล์

5) เมื่อตรวจสอบบันทึกเครือข่ายเมื่อพยายามสตรีมสดฉันได้รับคำขอเริ่มต้นที่ถูกยกเลิกโดยได้รับประมาณ 200 ไบต์เท่านั้นจากนั้นคำขอซ้ำอีกครั้งจะถูกยกเลิกด้วย 200 ไบต์และคำขอที่สามซึ่งมีความยาวเพียง 2K เท่านั้น ฉันไม่เข้าใจว่าทำไมไคลเอนต์ HTML5 จะยกเลิกการร้องขอเนื่องจาก bytestream เหมือนกับที่ฉันสามารถใช้งานได้สำเร็จเมื่อสตรีมจากไฟล์ที่บันทึกไว้ ดูเหมือนว่าโหนดไม่ได้ส่งสตรีม FFMPEG ที่เหลือไปยังไคลเอนต์ แต่ฉันสามารถดูข้อมูล FFMPEG ในรูทีนเหตุการณ์. on รูทีนเพื่อให้มันไปยังเซิร์ฟเวอร์ HTTP HTTP โหนด FFMPEG

6) แม้ว่าฉันคิดว่าการไพพ์สตรีม STDOUT ไปยังบัฟเฟอร์การตอบสนอง HTTP ควรใช้งานได้หรือไม่ฉันต้องสร้างบัฟเฟอร์ระดับกลางและสตรีมที่อนุญาตให้ไคลเอนต์เนื้อหา HTTP บางส่วนทำงานได้อย่างถูกต้องเหมือนที่มันทำเมื่ออ่านไฟล์สำเร็จ ? ฉันคิดว่านี่เป็นเหตุผลหลักสำหรับปัญหาของฉัน แต่ฉันไม่แน่ใจว่าในโหนดวิธีการตั้งค่าที่ดีที่สุด และฉันไม่รู้วิธีจัดการกับคำขอของลูกค้าสำหรับข้อมูลที่ส่วนท้ายของไฟล์เนื่องจากไม่มีจุดสิ้นสุดไฟล์

7) ฉันอยู่ผิดทางโดยพยายามจัดการคำขอเนื้อหาบางส่วน 206 รายการและควรทำงานกับการตอบกลับ HTTP 200 ปกติหรือไม่ การตอบสนอง HTTP 200 ทำงานได้ดีสำหรับ VLC ดังนั้นฉันสงสัยว่าไคลเอนต์วิดีโอ HTML5 จะทำงานกับคำขอเนื้อหาบางส่วนเท่านั้น

ในขณะที่ฉันยังคงเรียนรู้สิ่งนี้มันยากที่จะทำงานผ่านเลเยอร์ต่าง ๆ ของปัญหานี้ (FFMPEG, โหนด, สตรีมมิ่ง, HTTP, วิดีโอ HTML5) เพื่อให้พอยน์เตอร์ใด ๆ ได้รับการชื่นชมอย่างมาก ฉันใช้เวลาหลายชั่วโมงทำการค้นคว้าในเว็บไซต์นี้และในเน็ตและฉันไม่เคยเจอใครที่สามารถทำการสตรีมมิ่งแบบเรียลไทม์ในโหนด แต่ฉันไม่สามารถเป็นคนแรกและฉันคิดว่ามันควรจะทำงานได้ !)


4
เรื่องนี้เป็นเรื่องยาก สิ่งแรกคือสิ่งแรก คุณตั้งContent-Typeหัวของคุณหรือไม่? คุณใช้การเข้ารหัสก้อนหรือไม่? นั่นคือสิ่งที่ฉันจะเริ่มต้น นอกจากนี้ HTML5 ไม่จำเป็นต้องให้การทำงานเพื่อสตรีมคุณสามารถอ่านเพิ่มเติมเกี่ยวกับที่นี่ คุณจะต้องใช้วิธีการบัฟเฟอร์และเล่นสตรีมวิดีโอโดยใช้วิธีการของคุณเอง ( ดูที่นี่ ) คิดว่าสิ่งนี้อาจไม่ได้รับการสนับสนุนอย่างดี นอกจากนี้ google ใน MediaSource API
tsturzl

ขอบคุณสำหรับการตอบกลับ. ใช่ประเภทเนื้อหาคือ 'วิดีโอ / mp4' และรหัสนี้ใช้งานได้กับการสตรีมไฟล์วิดีโอ น่าเสียดาย MediaSource เป็น Chrome เท่านั้นฉันต้องสนับสนุนเบราว์เซอร์อื่น มีข้อมูลจำเพาะเกี่ยวกับวิธีที่ไคลเอ็นต์วิดีโอ HTML5 โต้ตอบกับเซิร์ฟเวอร์การสตรีม HTTP หรือไม่ ฉันแน่ใจว่าสิ่งที่ฉันต้องการที่จะสามารถทำได้แค่ไม่แน่ใจว่าวิธีการ (กับ Node.js แต่สามารถใช้ C # หรือ C ++ ถ้าได้ง่ายขึ้น)
deandob

2
ปัญหาไม่ได้อยู่ในแบ็กเอนด์ของคุณ คุณสตรีมวิดีโอได้ดี ปัญหาอยู่ในส่วนหน้า / ไคลเอนต์ของคุณคุณต้องทำการสตรีมด้วยตัวเอง HTML5 ไม่รองรับการสตรีม คุณจะต้องสำรวจตัวเลือกต่อเบราว์เซอร์มากที่สุด การอ่านมาตรฐาน w3 สำหรับแท็กวิดีโอและ API สื่อจะเป็นจุดเริ่มต้นที่ดี
tsturzl

ดูเหมือนว่ามันควรจะเป็นไปได้ที่จะทำให้งานนี้ ฉันไม่ได้เสนอคำตอบที่ชัดเจน แต่ฉันสงสัยว่าปัญหานี้เกี่ยวข้องกับความจริงที่ว่าเบราว์เซอร์คาดว่าส่วนหัวของคอนเทนเนอร์ mp4 / อะตอมที่เหลืออยู่ที่จุดเริ่มต้นไม่ใช่เฟรมถัดไปในสตรีมวิดีโอ หากคุณส่ง MOOV atom สำหรับวิดีโอที่มีความยาวมาก (เพื่อให้เครื่องเล่นทำการร้องขอ) รวมถึงส่วนหัวอื่น ๆ ที่คาดไว้จากนั้นเริ่มคัดลอกจาก ffmpeg สิ่งนี้อาจใช้ได้ คุณจะต้องซ่อนแถบขัดผิวหน้าด้วย js ในเบราว์เซอร์เพื่อไม่ให้สแกนไปข้างหน้า
jwriteclub

ฉันขอแนะนำให้พิจารณาWebRTCซึ่งได้รับการสนับสนุนข้ามเบราว์เซอร์ที่ดีขึ้นทุกวัน
Alex Cohn

คำตอบ:


209

แก้ไข 3: ตั้งแต่ iOS 10, HLS จะรองรับไฟล์ mp4 แบบแยกส่วน คำตอบตอนนี้คือการสร้างเนื้อหา mp4 แยกส่วนด้วย DASH และ HLS รายการ > แกล้งทำเป็น Flash, iOS9 และต่ำกว่าและ IE 10 และต่ำกว่านั้นไม่มีอยู่จริง

ทุกอย่างที่อยู่ใต้บรรทัดนี้ล้าสมัย เก็บไว้ที่นี่เพื่อลูกหลาน


แก้ไข 2: เนื่องจากผู้คนในความคิดเห็นต่างชี้ให้เห็นสิ่งต่าง ๆ จึงเปลี่ยนไป เบราว์เซอร์เกือบทั้งหมดจะรองรับตัวแปลงสัญญาณ AVC / AAC iOS ยังคงต้องการ HLS แต่ผ่านอะแดปเตอร์เช่น hls.js คุณสามารถเล่น HLS ใน MSE คำตอบใหม่คือ HLS + hls.js หากคุณต้องการ iOS หรือเพียงแค่แยกส่วน MP4 (เช่น DASH) ถ้าคุณทำไม่ได้

มีหลายสาเหตุที่วิดีโอและโดยเฉพาะวิดีโอสดนั้นยากมาก (โปรดทราบว่าคำถามเดิมระบุว่าวิดีโอ HTML5 นั้นเป็นข้อกำหนด แต่ผู้ถามที่ระบุ Flash สามารถทำได้ในการแสดงความคิดเห็นดังนั้นในทันทีคำถามนี้ทำให้เข้าใจผิด)

ครั้งแรกที่ฉันจะย้ำ: มีการสนับสนุนอย่างเป็นทางการสำหรับการถ่ายทอดสดสตรีมมิ่งผ่าน HTML5 มีแฮ็ก แต่ระยะของคุณอาจแตกต่างกันไป

แก้ไข: ตั้งแต่ฉันเขียนคำตอบนี้ส่วนขยายแหล่งที่มาของสื่อได้ครบกำหนดและตอนนี้ใกล้จะกลายเป็นตัวเลือกที่ทำงานได้ พวกเขาได้รับการสนับสนุนในเบราว์เซอร์ที่สำคัญที่สุด IOS ยังคงถูกระงับอยู่

ถัดไปคุณต้องเข้าใจว่าวิดีโอตามคำขอ (VOD) และวิดีโอสดแตกต่างกันมาก ใช่พวกเขาเป็นทั้งวิดีโอ แต่ปัญหาต่างกันดังนั้นรูปแบบจึงแตกต่างกัน ตัวอย่างเช่นหากนาฬิกาในคอมพิวเตอร์ของคุณทำงานเร็วกว่าที่ควร 1% คุณจะไม่สังเกตเห็น VOD ด้วยวิดีโอสดคุณจะพยายามเล่นวิดีโอก่อนที่จะเกิดขึ้น หากคุณต้องการเข้าร่วมสตรีมมิ่งวิดีโอสดคุณต้องมีข้อมูลที่จำเป็นในการเริ่มต้นตัวถอดรหัสดังนั้นจะต้องทำซ้ำในสตรีมหรือส่งออกนอกแบนด์ ด้วย VOD คุณสามารถอ่านจุดเริ่มต้นของไฟล์ที่พวกเขาต้องการในทุกจุดที่คุณต้องการ

ทีนี้มาขุดกันหน่อย

แพลตฟอร์ม:

  • iOS
  • พีซี
  • Mac
  • Android

ตัวแปลงสัญญาณ:

  • VP8 / 9
  • h.264
  • ธ อร่า (vp3)

วิธีการจัดส่งทั่วไปสำหรับวิดีโอสดในเบราว์เซอร์:

  • DASH (HTTP)
  • HLS (HTTP)
  • แฟลช (RTMP)
  • แฟลช (HDS)

วิธีการจัดส่งทั่วไปสำหรับ VOD ในเบราว์เซอร์:

  • DASH (HTTP Streaming)
  • HLS (สตรีมมิ่ง HTTP)
  • แฟลช (RTMP)
  • แฟลช (HTTP สตรีมมิ่ง)
  • MP4 (การส่งข้อมูล HTTP หลอก)
  • ฉันจะไม่พูดเกี่ยวกับ MKV และ OOG เพราะฉันไม่รู้จักพวกเขาดีนัก

แท็กวิดีโอ html5:

  • MP4
  • webm
  • OGG

ให้ดูว่าเบราว์เซอร์ใดสนับสนุนรูปแบบใดบ้าง

Safari:

  • HLS (iOS และ Mac เท่านั้น)
  • h.264
  • MP4

Firefox

  • DASH (ผ่าน MSE แต่ไม่มี h.264)
  • h.264 ผ่าน Flash เท่านั้น!
  • VP9
  • MP4
  • OGG
  • Webm

IE

  • แฟลช
  • DASH (ผ่าน MSE IE 11+ เท่านั้น)
  • h.264
  • MP4

โครเมียม

  • แฟลช
  • DASH (ผ่าน MSE)
  • h.264
  • VP9
  • MP4
  • webm
  • OGG

ไม่สามารถใช้ MP4 สำหรับวิดีโอสด (หมายเหตุ: DASH คือชุดของ MP4 ดังนั้นอย่าสับสนกับเรื่องนี้) MP4 แบ่งออกเป็นสองส่วน: moov และ mdat mdat มีข้อมูลวิดีโอเสียงดิบ แต่มันไม่ได้จัดทำดัชนีดังนั้นโดยไม่มี moov มันไม่มีประโยชน์ moov มีดัชนีของข้อมูลทั้งหมดใน mdat แต่เนื่องจากรูปแบบของมันจึงไม่สามารถ 'แบน' จนกว่าจะทราบเวลาและขนาดของเฟรมทุกครั้ง มันอาจเป็นไปได้ที่จะสร้าง moov ที่ 'fibs' ขนาดของเฟรม แต่เป็นแบนด์วิดธ์ที่สิ้นเปลืองอย่างชาญฉลาด

ดังนั้นหากคุณต้องการส่งมอบทุกที่เราจำเป็นต้องค้นหาตัวหารร่วมน้อยที่สุด คุณจะเห็นว่าไม่มี LCD ในที่นี้หากไม่ใช้แฟลชตัวอย่าง:

  • iOS รองรับเฉพาะวิดีโอ h.264 และรองรับ HLS สำหรับการถ่ายทอดสดเท่านั้น
  • Firefox ไม่รองรับ h.264 เลยเว้นแต่ว่าคุณจะใช้แฟลช
  • Flash ไม่ทำงานใน iOS

สิ่งที่ใกล้เคียงที่สุดกับ LCD คือการใช้ HLS เพื่อรับผู้ใช้ iOS ของคุณและแฟลชสำหรับทุกคน สิ่งที่ฉันชอบส่วนตัวคือเข้ารหัส HLS จากนั้นใช้แฟลชเพื่อเล่น HLS สำหรับทุกคน คุณสามารถเล่น HLS ในแฟลชผ่าน JW player 6, (หรือเขียน HLS ของคุณเองเพื่อ FLV ใน AS3 เหมือนที่ฉันทำ)

ในไม่ช้าวิธีที่พบได้บ่อยที่สุดคือ HLS บน iOS / Mac และ DASH ผ่าน MSE ทุกที่อื่น (นี่คือสิ่งที่ Netflix จะทำในไม่ช้า) แต่เรายังคงรอให้ทุกคนอัปเกรดเบราว์เซอร์ คุณอาจต้องแยก DASH / VP9 สำหรับ Firefox (ฉันรู้เกี่ยวกับ open264 มันแย่มากมันไม่สามารถทำวิดีโอในโปรไฟล์หลักหรือโปรไฟล์สูงได้


ขอบคุณ szatmary สำหรับรายละเอียดพื้นหลังและโปร / ข้อเสียเกี่ยวกับตัวเลือกต่าง ๆ ฉันได้เลือกคำตอบนี้เป็นคำตอบที่ได้รับการยอมรับว่าเป็นโครงร่างของแนวคิดมีความสำคัญมากกว่าการแก้ไขเฉพาะที่ฉันพบเพื่อตอบคำถามต้นฉบับ ขอให้โชคดีกับความโปรดปราน!
deandob

9
นี่ไม่ใช่วิธีแก้ปัญหาสำหรับคำถามนี้ มีวิธีแก้ไขปัญหาการทำงานด้านล่างนี้
jwriteclub

2
Firefox รองรับ MSE และ h.264 อย่างเป็นทางการแล้ว ไปที่ www.youtube.com/html5 ด้วยเบราว์เซอร์ FF ล่าสุดเพื่อยืนยัน ฉันทดสอบกับ FF 37 แล้ว Safari 8+ บน Mac ก็รองรับ MSE เช่นกัน
BigTundra

@ BigTundra ใช่แล้ว Safari ได้รองรับ MSE ตั้งแต่เปิดตัวโยเซมิตีบน Mac แต่ไม่ใช่ iOS ไม่แน่ใจเกี่ยวกับ Windows (ซาฟารีบน windows ยังคงเป็นอะไรหรือเปล่า) Firefox 37.0.2 on (ของฉัน) Mac ดูเหมือนจะไม่สนับสนุน MSE เลยตามลิงค์นั้น แต่รองรับ H.264 Firefox ได้เพิ่มและลบและสนับสนุน H.264 อีกครั้งในอดีต
szatmary

เบราว์เซอร์ที่ทันสมัยรองรับรูปแบบวิดีโอ MPEG-4 / H.264: caniuse.com/#feat=mpeg4
Maxence

75

ขอบคุณทุกคนโดยเฉพาะอย่างยิ่ง szatmary เนื่องจากนี่เป็นคำถามที่ซับซ้อนและมีเลเยอร์มากมายให้ทุกคนต้องทำงานก่อนที่คุณจะสามารถสตรีมวิดีโอสดได้ เพื่อชี้แจงคำถามเดิมของฉันและการใช้วิดีโอ HTML5 กับแฟลช - กรณีการใช้งานของฉันมีการตั้งค่าที่แข็งแกร่งสำหรับ HTML5 เพราะเป็นเรื่องทั่วไปที่ง่ายต่อการใช้งานกับลูกค้าและอนาคต Flash นั้นดีที่สุดเป็นอันดับสองดังนั้นลองติดกับ HTML5 สำหรับคำถามนี้

ฉันได้เรียนรู้มากมายจากแบบฝึกหัดนี้และยอมรับว่าการสตรีมสดนั้นยากกว่า VOD (ซึ่งทำงานได้ดีกับวิดีโอ HTML5) แต่ฉันทำให้เรื่องนี้ทำงานได้อย่างน่าพอใจสำหรับกรณีการใช้งานของฉันและวิธีการแก้ปัญหานั้นง่ายมากหลังจากไล่ตามตัวเลือกที่ซับซ้อนมากขึ้นเช่น MSE, flash, รูปแบบบัฟเฟอร์ที่ซับซ้อนใน Node ปัญหาคือ FFMPEG กำลังทำลาย MP4 ที่แยกส่วนและฉันต้องปรับพารามิเตอร์ FFMPEG และการเปลี่ยนเส้นทางไปป์ของโหนดโหนดมาตรฐานผ่าน http ที่ฉันใช้ในตอนแรกนั้นเป็นสิ่งที่จำเป็นทั้งหมด

ใน MP4 มีตัวเลือก 'การแตกแฟรกเมนต์' ที่แบ่ง mp4 ออกเป็นชิ้นเล็ก ๆ ซึ่งมีดัชนีเป็นของตัวเองและทำให้ตัวเลือกการสตรีมสด mp4 ทำงานได้ แต่เป็นไปไม่ได้ที่จะค้นหากลับเข้าไปในกระแส (ตกลงสำหรับกรณีการใช้งานของฉัน) และ FFMPEG รุ่นที่ใหม่กว่าสนับสนุนการกระจายตัว

การจับเวลาเวลาอาจเป็นปัญหาและด้วยวิธีแก้ปัญหาของฉันฉันมีความล่าช้าระหว่าง 2 และ 6 วินาทีที่เกิดจากการรวมกันของ remuxing (FFMPEG ที่มีประสิทธิภาพต้องได้รับกระแสสดจากนั้นทำการรีมมันไปยังโหนดเพื่อให้บริการ HTTP) . ไม่สามารถทำได้มากนักเกี่ยวกับเรื่องนี้อย่างไรก็ตามใน Chrome วิดีโอพยายามที่จะไล่ตามให้มากที่สุดเท่าที่จะทำได้ซึ่งทำให้วิดีโอดูน่ากลัว แต่เป็นปัจจุบันมากกว่า IE11 (ไคลเอนต์ที่ฉันต้องการ)

แทนที่จะอธิบายวิธีการทำงานของรหัสในโพสต์นี้ให้ตรวจสอบ GIST ด้วยความคิดเห็น (ไม่รวมรหัสลูกค้าเป็นแท็กวิดีโอ HTML5 มาตรฐานที่มีที่อยู่เซิร์ฟเวอร์โหนด http) รายการอยู่ที่นี่: https://gist.github.com/deandob/9240090

ฉันไม่สามารถหาตัวอย่างที่คล้ายกันของกรณีการใช้งานนี้ได้ดังนั้นฉันหวังว่าคำอธิบายข้างต้นและรหัสจะช่วยผู้อื่นโดยเฉพาะอย่างยิ่งเมื่อฉันได้เรียนรู้มากมายจากเว็บไซต์นี้และยังถือว่าฉันเป็นมือใหม่!

แม้ว่านี่จะเป็นคำตอบสำหรับคำถามเฉพาะของฉัน แต่ฉันได้เลือกคำตอบของ szatmary เป็นคำตอบที่ได้รับการยอมรับมากที่สุด


33
ขออภัยที่ฉันพบสิ่งนี้ด้วยตัวเองการเขียนคำตอบของฉันทำให้ชัดเจน คำตอบก่อนหน้านี้ทั้งหมดเป็นประโยชน์และชื่นชม แต่ไม่ได้มีส่วนสำคัญและฉันยังส่งรหัสการทำงานใน GIST และไม่มีใครมี ฉันไม่สนใจใน 'ชื่อเสียง' ฉันสนใจที่จะเรียนรู้ที่จะรู้ว่าวิธีการและรหัสของฉันสามารถปรับปรุงได้หรือไม่ และคำตอบที่ฉันเลือกไว้ก็ช่วยแก้ปัญหาของฉันได้ดังนั้นฉันจึงสับสนกับสิ่งที่เป็นปัญหาอยู่ที่นี่ ฉันค่อนข้างใหม่ดังนั้นฉันจึงดีใจที่ได้รับคำแนะนำให้โต้ตอบในวิธีอื่นฉันพบว่าไซต์นี้มีประโยชน์และคำตอบของฉันควรช่วยเหลือผู้อื่น
deandob

2
ดูเหมือนว่าไม่ใช่สิ่งที่ถูกต้องในชุมชนนี้เพื่อเลือกคำตอบของคุณเป็นคำตอบที่ยอมรับถ้าคุณถามคำถามแม้ว่าจะแก้ปัญหาเดิมได้ แม้ว่ามันจะดูเป็นเรื่องที่ขัดกับตัวเอง แต่เอกสารของแนวคิดมีความสำคัญมากกว่าการแก้ไขจริงซึ่งฉันก็โอเคเพราะมันช่วยให้ผู้อื่นเรียนรู้ ฉันได้ยกเลิกการเลือกคำตอบและเลือก szatmary ว่าเป็นคำที่ชัดเจนที่สุดในแนวคิด
deandob

6
@deandob: ฉันโพสต์เงินรางวัลสำหรับการแก้ปัญหาการทำงานกับปัญหานี้ซึ่งคุณให้ไว้เรียบร้อยแล้ว คำตอบที่ยอมรับได้ยืนยันว่าไม่มีวิธีแก้ปัญหาการทำงานและดังนั้นจึงไม่ถูกต้องอย่างชัดเจน
jwriteclub

2
ขอบคุณ ดูเหมือนว่าคนอื่น ๆ ได้ปฏิเสธคำตอบดั้งเดิมของฉันผิดและฉันใหม่ฉันเพิ่งสันนิษฐานว่าเป็นสิ่งที่ทำงานรอบ ๆ ที่นี่ ฉันไม่ต้องการที่จะทำให้เกิดความยุ่งยาก แต่ฉันจะตรวจสอบกับคนในเมตากองล้น BTW - โซลูชันของฉันทำงานได้ดีมากและควรใช้งานได้กับผู้อื่นและมีการเปลี่ยนแปลงในโซลูชันที่โพสต์ซึ่งสามารถลดความล่าช้าเริ่มต้นได้ (บัฟเฟอร์ใน node.js เริ่มแรกแล้วหาทางจบสตรีมที่ปลายไคลเอนต์) .
deandob

4
ฉันมีคำชี้แจงจากผู้ดำเนินรายการว่าวิธีการดั้งเดิมของฉันในการตอบคำถามด้วยตนเองและเลือกว่าเนื่องจากคำตอบนั้นเป็นวิธีการที่ถูกต้อง สำหรับข้อมูลเพิ่มเติม (หรือถ้าคุณต้องการที่จะอภิปรายเพิ่มเติมนี้) ดูกระทู้ในเว็บไซต์เมตา meta.stackexchange.com/questions/224068/…
deandob

14

ลองดูที่โครงการJSMPEG มีความคิดที่ดีในการนำไปใช้เพื่อถอดรหัส MPEG ในเบราว์เซอร์โดยใช้ JavaScript ไบต์จากตัวเข้ารหัส (ตัวอย่างเช่น FFMPEG) สามารถถ่ายโอนไปยังเบราว์เซอร์โดยใช้ WebSockets หรือ Flash เป็นต้น ถ้าชุมชนจะทันฉันคิดว่ามันจะเป็นทางออกสตรีมมิ่งวิดีโอ HTML5 ที่ดีที่สุดสำหรับตอนนี้


10
นั่นคือตัวถอดรหัสวิดีโอ MPEG-1 ฉันไม่แน่ใจว่าคุณเข้าใจว่า MPEG-1 นั้นโบราณแค่ไหน; มันเก่ากว่าดีวีดี มันเป็นเรื่องเล็กน้อยสูงกว่าไฟล์ GIF
Camilo Martin

13

ฉันเขียนโปรแกรมเล่นวิดีโอ HTML5 รอบ ๆ h264 codec (emscripten) ที่สามารถเล่นวิดีโอสด (ไม่ล่าช้า) h264 บนเบราว์เซอร์ทั้งหมด (เดสก์ท็อป, iOS, ... )

วิดีโอสตรีมถูกส่งผ่าน websocket ไปยังลูกค้าถอดรหัสเฟรมต่อเฟรมและแสดงเป็น canva (ใช้ webgl เพื่อเร่งความเร็ว)

ตรวจสอบhttps://github.com/131/h264-live-playerบน github


1
github.com/Streamedian/html5_rtsp_playerพวกนี้ทำสิ่งที่คล้ายกันซึ่งใช้ rtp h264 ผ่าน websocket
Victor.dMdB

12

วิธีหนึ่งในการถ่ายทอดสดเว็บแคมที่ใช้ RTSP ไปยังไคลเอนต์ HTML5 (เกี่ยวข้องกับการเข้ารหัสซ้ำดังนั้นคาดว่าจะสูญเสียคุณภาพและต้องการ CPU-power บางตัว):

  • ตั้งค่าเซิร์ฟเวอร์ icecast (อาจอยู่ในเครื่องเดียวกับที่เว็บเซิร์ฟเวอร์ของคุณอยู่บนหรือบนเครื่องที่ได้รับ RTSP-stream จากลูกเบี้ยว)
  • บนเครื่องที่ได้รับกระแสจากกล้องอย่าใช้ FFMPEG แต่เป็น gstreamer สามารถรับและถอดรหัส RTSP-stream เข้ารหัสใหม่และสตรีมไปยังเซิร์ฟเวอร์ icecast ตัวอย่างไปป์ไลน์ (เฉพาะวิดีโอไม่มีเสียง):

    gst-launch-1.0 rtspsrc location=rtsp://192.168.1.234:554 user-id=admin user-pw=123456 ! rtph264depay ! avdec_h264 ! vp8enc threads=2 deadline=10000 ! webmmux streamable=true ! shout2send password=pass ip=<IP_OF_ICECAST_SERVER> port=12000 mount=cam.webm

=> คุณสามารถใช้แท็ก <video> กับ URL ของ icecast-stream ( http://127.0.0.1:12000/cam.webm ) และมันจะใช้ได้กับทุกเบราว์เซอร์และอุปกรณ์ที่รองรับ webm


3

ลองดูโซลูชันนี้ อย่างที่ทราบ Flashphoner อนุญาตให้เล่นสตรีมเสียง + วิดีโอสดในหน้า HTML5 แท้

พวกเขาใช้ตัวแปลงสัญญาณMPEG1และG.711สำหรับการเล่น แฮ็คกำลังแสดงผลวิดีโอที่ถอดรหัสไปยังองค์ประกอบผ้าใบ HTML5 และเล่นเสียงถอดรหัสผ่านบริบทเสียง HTML5



2

นี่เป็นความเข้าใจผิดที่พบบ่อยมาก ไม่มีการสนับสนุนวิดีโอ HTML5 แบบสด (ยกเว้น HLS บน iOS และ Mac Safari) คุณอาจสามารถ 'แฮ็ค' โดยใช้ webm container แต่ฉันไม่คาดหวังว่าจะได้รับการสนับสนุนในระดับสากล สิ่งที่คุณกำลังค้นหารวมอยู่ใน Media Source Extensions ซึ่งคุณสามารถป้อนชิ้นส่วนให้กับเบราว์เซอร์ได้ทีละรายการ แต่คุณจะต้องเขียนจาวาสคริปต์ฝั่งไคลเอ็นต์


มีsolutionsแต่ไม่มีsupportสำหรับการสตรีมสด นี่คือการอ้างอิงโดยตรงกับความคิดเห็นของฉันที่เห็นด้านบน และ webm รองรับเบราว์เซอร์หลักส่วนใหญ่เป็นเวอร์ชันเสถียรล่าสุด
tsturzl

1
ฉันไม่ต้องการแปลงจาก H.264 เป็น webm และไม่จำเป็นต้องทำ นอกจากนี้เนื่องจากฉันต้องรองรับ IE11 และ Safari ส่วนขยาย MediaSource จะไม่ช่วย แต่ฉันคิดว่าถ้าฉันจำลองสตรีมไฟล์ที่ฝั่งเซิร์ฟเวอร์ (ซึ่งใช้งานได้!) มันควรจะใช้ได้ แต่ฉันจะต้องจำลองไฟล์บัฟเฟอร์บน node.js
deandob

1
ตามที่แนะนำอื่น ๆ ฉันจะขอโอกาสในการใช้ WebRTC ซึ่งเป็นภาษาที่แตกต่างจาก VLC หรือปลั๊กอินแฟลช ฉันรู้ว่าเทคโนโลยีนี้ยังคงใช้งานยาก โชคดี.

1
ฉันได้รับสิ่งนี้เพื่อทำงานโดยอัปเดตเป็น FFMPEG เวอร์ชันล่าสุดเนื่องจากดูเหมือนว่ามีความเสียหายใน mp4 เมื่อใช้โหมดการแยกส่วน (จำเป็นสำหรับการสตรีมสด MP4 ดังนั้นไคลเอนต์ไม่รอไฟล์ดัชนี moov ซึ่งจะไม่มาเมื่ออยู่ สตรีมมิ่ง) และรหัส node.js ของฉันเพื่อเปลี่ยนเส้นทางสตรีม FFMPEG ไปยังเบราว์เซอร์โดยตรงในขณะนี้
deandob

1
ใช่ทำงานได้ดีบน IE11 (เบราว์เซอร์ที่ฉันต้องการ) ฉันได้รับการตอบสนองที่น่ากลัวใน Chrome
deandob

2

ลอง binaryjs มันเหมือนกับ socket.io แต่สิ่งเดียวที่ทำได้ดีคือมันสตรีมวิดีโอเสียง Binaryjs google it


1
Binary.JS ไม่เหมือน Socket.IO และไม่เฉพาะเจาะจงกับการสตรีมสื่อ
แบรด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.