หากคุณทำงานกับส่วนขยายแหล่งที่มาของสื่อ (MSE) สิ่งหนึ่งที่คุณจะต้องจัดการในท้ายที่สุดคือบัฟเฟอร์ที่มากเกินไป เมื่อเกิดเหตุการณ์นี้
คุณจะได้รับสิ่งที่เรียกว่า QuotaExceededError
ในบทความนี้ ผมจะพูดถึงบางวิธี
ในการจัดการปัญหานี้
QuotaExceededError คืออะไร
โดยทั่วไปแล้ว QuotaExceededError
คือสิ่งที่คุณจะได้รับหากพยายามเพิ่มข้อมูลมากเกินไปลงในออบเจ็กต์ SourceBuffer
(การเพิ่มออบเจ็กต์ SourceBuffer
ในองค์ประกอบ MediaSource
ระดับบนสุดอาจทำให้เกิดข้อผิดพลาดนี้ได้เช่นกัน ซึ่งอยู่นอกเหนือขอบเขตของบทความนี้) หาก SourceBuffer
มีข้อมูลมากเกินไป การเรียกใช้ SourceBuffer.appendBuffer()
จะทริกเกอร์ข้อความต่อไปนี้ในหน้าต่างคอนโซลของ Chrome
มี 2-3 อย่างที่ควรทราบเกี่ยวกับเรื่องนี้ ขั้นแรก โปรดทราบว่าชื่อ QuotaExceededError
จะไม่ปรากฏในข้อความ หากต้องการดูจุดนี้ ให้กำหนดเบรกพอยท์ ณ ตำแหน่งที่คุณสามารถตรวจจับข้อผิดพลาดและตรวจสอบใน
นาฬิกาหรือหน้าต่างขอบเขตได้ เราแสดงไว้ด้านล่างนี้
ประการที่ 2 ไม่มีวิธีที่แน่นอนในการค้นหาปริมาณข้อมูลที่ SourceBuffer
จะจัดการได้
ลักษณะการทำงานในเบราว์เซอร์อื่น
ตอนที่เขียน Safari ไม่ได้ใช้ QuotaExceededError
ในบิวด์หลายๆ รุ่น แต่จะนำเฟรมออกโดยใช้อัลกอริทึมแบบ 2 ขั้นตอนแทน และจะหยุดเมื่อมีพื้นที่เพียงพอที่จะจัดการ appendBuffer()
ข้อแรก จะทำให้เฟรมว่างระหว่าง 0 ถึง 30 วินาทีก่อนเวลาปัจจุบันในช่วงเวลา 30 วินาที จากนั้นจะปล่อยเฟรมจากระยะเวลา 30 วินาทีจากระยะเวลาย้อนกลับไปจนถึง 30 วินาทีหลังจาก currentTime
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ใน Webkit Changeset จากปี 2014
อย่างไรก็ตาม นอกจาก Chrome, Edge และ Firefox จะพบข้อผิดพลาดนี้แล้ว หากใช้เบราว์เซอร์อื่น คุณจะต้องทำการทดสอบด้วยตนเอง แม้ว่าอาจไม่ใช่สิ่งที่คุณสร้างสำหรับโปรแกรมเล่นสื่อในชีวิตจริง แต่การทดสอบขีดจำกัดบัฟเฟอร์ต้นทางของ François Beaufort จะช่วยให้คุณสังเกตพฤติกรรมได้
ฉันสามารถเพิ่มข้อมูลได้มากน้อยแค่ไหน
ตัวเลขที่แน่นอนจะแตกต่างกันไปตามแต่ละเบราว์เซอร์ เนื่องจากคุณไม่สามารถค้นหาจำนวน ข้อมูลที่ต่อท้ายในปัจจุบันได้ คุณจะต้องติดตามจำนวนเงินที่เพิ่ม เองด้วย สำหรับข้อมูลที่จะดู นี่เป็นข้อมูลที่ดีที่สุด ที่เราสามารถรวบรวมได้ตอนที่เขียน สำหรับ Chrome ตัวเลขเหล่านี้เป็นขีดจำกัดสูงสุด หมายความว่าตัวเลขจะน้อยลงเมื่อระบบพบปริมาณหน่วยความจำ
Chrome | Chromecast* | Firefox | Safari | Edge | |
---|---|---|---|---|---|
วิดีโอ | 150MB | 30MB | 100 MB | 290MB | ไม่ทราบ |
เสียง | 12MB | 2MB | 15 MB | 14MB | ไม่ทราบ |
- หรืออุปกรณ์ Chrome ที่มีหน่วยความจำจำกัดอื่นๆ
แล้วฉันต้องทำอย่างไร
เนื่องจากปริมาณข้อมูลที่รองรับมีความแตกต่างกันมาก คุณจึงไม่เห็นจำนวนข้อมูลใน SourceBuffer
คุณจึงต้องรับข้อมูลโดยอ้อมโดยการจัดการ QuotaExceededError
มาดูวิธีทำกันเลย
วิธีการจัดการกับ QuotaExceededError
มีอยู่หลายวิธี ในความเป็นจริงการใช้หลายๆ วิธีรวมกันจะดีที่สุด วิธีการของคุณควรอิงตามจำนวนที่คุณดึงข้อมูลและพยายามเพิ่มต่อท้าย HTMLMediaElement.currentTime
และปรับขนาดตาม QuotaExceededError
นอกจากนี้ การใช้ไฟล์ Manifest บางประเภท เช่น ไฟล์ mpd
(MPEG-DASH) หรือไฟล์ m3u8
(HLS) จะช่วยให้คุณติดตามข้อมูลที่คุณเพิ่มลงในบัฟเฟอร์ได้
ตอนนี้เรามาดูวิธีต่างๆ ในการจัดการกับ QuotaExceededError
กัน
- นำข้อมูลที่ไม่จำเป็นออกแล้วเพิ่มกลับเข้าไปใหม่
- ต่อท้ายส่วนย่อยที่เล็กกว่า
- ลดความละเอียดในการเล่นลง
แม้ว่าจะใช้ผสมกันได้ แต่เราจะบดบังผลิตภัณฑ์ทีละรายการ
นำข้อมูลที่ไม่จำเป็นออกแล้วเพิ่มกลับเข้าไปใหม่
อันที่จริงเราเรียกรหัสนี้ว่า "ลบข้อมูลที่มีแนวโน้มว่าจะมีการใช้งานน้อยที่สุด แล้วลองต่อท้ายข้อมูลที่มีแนวโน้มว่าจะมีการใช้เร็วๆ นี้" ชื่อยาวเกินไป คุณแค่ต้องจำว่าฉันหมายถึงอะไรจริงๆ
การนำข้อมูลล่าสุดออกไม่ใช่เรื่องง่ายเหมือนการโทรหา SourceBuffer.remove()
หากต้องการนำข้อมูลออกจาก SourceBuffer
แฟล็กการอัปเดตนั้นต้องเป็น "เท็จ" หากไม่ใช่ ให้เรียกใช้ SourceBuffer.abort()
ก่อนที่จะนำข้อมูลออก
สิ่งที่ควรคำนึงถึงเมื่อโทรหา SourceBuffer.remove()
มีดังนี้
- วิธีนี้อาจส่งผลเสียต่อการเล่น ตัวอย่างเช่น หากคุณต้องการให้วิดีโอเล่นซ้ำหรือเล่นวนซ้ำในเร็วๆ นี้ คุณอาจไม่ต้องการลบช่วงต้นของวิดีโอ ในทำนองเดียวกัน หากคุณหรือผู้ใช้ค้นหาส่วนของวิดีโอที่นำข้อมูลออก คุณจะต้องต่อข้อมูลดังกล่าวอีกครั้งเพื่อตอบสนองความต้องการดังกล่าว
- โปรดนำออกอย่างระมัดระวังที่สุดเท่าที่จะทำได้ โปรดระวังการนำกลุ่มเฟรมที่กำลังเล่นอยู่ออก ซึ่งเริ่มต้นจากคีย์เฟรม ณ หรือก่อน
currentTime
เนื่องจากการทำเช่นนั้นอาจทำให้การเล่นค้าง เว็บแอปอาจต้องแยกวิเคราะห์ข้อมูลดังกล่าวออกจากไบท์สตรีม หากไม่มีอยู่ในไฟล์ Manifest ไฟล์ Manifest ของสื่อหรือความรู้เกี่ยวกับช่วงคีย์เฟรมในสื่อจะช่วยแนะแนวทางในการเลือกช่วงการนำออกของแอปเพื่อป้องกันไม่ให้มีการนำสื่อที่กำลังเล่นอยู่ออก ไม่ว่าคุณจะนำภาพใดออก อย่านำกลุ่มภาพที่กำลังเล่นอยู่ออก หรือแม้แต่รูปแรกๆ ไม่กี่รูป โดยทั่วไป อย่านำเวลาปัจจุบันออก เว้นแต่คุณแน่ใจว่าไม่จำเป็นต้องสื่อนั้นแล้ว หากนำออกไปไว้ใกล้กับส่วนหัวของตัวควบคุมการเล่น อาจทำให้หยุดทำงาน - Safari 9 และ Safari 10 ไม่ได้ติดตั้งใช้งาน
SourceBuffer.abort()
อย่างถูกต้อง อันที่จริงแล้ว แอปอาจมีข้อผิดพลาดที่ทำให้หยุดเล่นได้ โชคดีที่มีเครื่องมือติดตามข้อบกพร่อง ที่เปิดไว้ที่นี่ และที่นี่ ในระหว่างนี้ คุณจะต้องแก้ปัญหานี้ก่อน Shaka Player ทำได้ โดยตัดฟังก์ชันabort()
ที่ว่างเปล่าใน Safari เวอร์ชันเหล่านั้น
ต่อท้ายส่วนย่อยที่เล็กกว่า
เราได้แสดงขั้นตอนดำเนินการไว้ด้านล่าง ซึ่งอาจไม่ได้ผลกับทุกกรณี แต่ก็มีข้อได้เปรียบตรงที่ชิ้นขนาดเล็กๆ สามารถปรับขนาดให้เหมาะกับความต้องการได้ นอกจากนี้ยังไม่จำเป็นต้องกลับไปยังเครือข่าย ซึ่งอาจมีค่าใช้จ่ายเพิ่มเติมสำหรับข้อมูลสำหรับผู้ใช้บางราย
const pieces = new Uint8Array([data]);
(function appendFragments(pieces) {
if (sourceBuffer.updating) {
return;
}
pieces.forEach(piece => {
try {
sourceBuffer.appendBuffer(piece);
}
catch e {
if (e.name !== 'QuotaExceededError') {
throw e;
}
// Reduction schedule: 80%, 60%, 40%, 20%, 16%, 12%, 8%, 4%, fail.
const reduction = pieces[0].byteLength * 0.8;
if (reduction / data.byteLength < 0.04) {
throw new Error('MediaSource threw QuotaExceededError too many times');
}
const newPieces = [
pieces[0].slice(0, reduction),
pieces[0].slice(reduction, pieces[0].byteLength)
];
pieces.splice(0, 1, newPieces[0], newPieces[1]);
appendBuffer(pieces);
}
});
})(pieces);
ลดความละเอียดในการเล่น
ซึ่งคล้ายกับการนำข้อมูลล่าสุดออกและผนวกอีกครั้ง อันที่จริง ทั้งสองอย่างอาจทำงานด้วยกันได้ แม้ว่าตัวอย่างด้านล่างจะแสดงเฉพาะความละเอียดที่ลดลงเท่านั้น
เมื่อใช้เทคนิคนี้ คุณควรคำนึงถึงสิ่งต่อไปนี้
- คุณต้องผนวกกลุ่มการเริ่มต้นใหม่ คุณต้องทำเช่นนี้ทุกครั้งที่คุณเปลี่ยนตัวแทน กลุ่มการเริ่มต้นใหม่ต้องเป็นกลุ่มสื่อที่ตามมา
- การประทับเวลาการนำเสนอของสื่อที่ต่อท้ายควรตรงกับการประทับเวลาของข้อมูลในบัฟเฟอร์ให้ใกล้เคียงที่สุด แต่ไม่ควรข้ามไปข้างหน้า ข้อมูลที่บัฟเฟอร์ซ้อนทับกันอาจทำให้เกิดภาพกระตุกหรือหยุดทำงานชั่วขณะ ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ อย่าวางซ้อนส่วนหัวของตัวควบคุมการเล่น ไม่ว่าจะเพิ่มส่วนใดต่อท้าย เพราะจะทำให้เกิดข้อผิดพลาด
- การกรอวิดีโออาจขัดจังหวะการเล่น คุณอาจอยากค้นหาตำแหน่งที่เจาะจง และเล่นต่อจากตำแหน่งนั้น โปรดทราบว่าการดำเนินการนี้จะทำให้ การเล่นหยุดชะงักจนกว่าการค้นหาจะเสร็จสมบูรณ์