หากใช้ส่วนขยายแหล่งที่มาของสื่อ (MSE) สิ่งหนึ่งที่คุณต้องจัดการในที่สุดคือบัฟเฟอร์ที่เต็มมากเกินไป ในกรณีนี้ คุณจะได้รับสิ่งที่เรียกว่า QuotaExceededError
ในบทความนี้ เราจะพูดถึงวิธีจัดการกับปัญหาดังกล่าว
QuotaExceededError คืออะไร
โดยพื้นฐานแล้ว QuotaExceededError
คือสิ่งที่คุณจะได้รับหากพยายามเพิ่มข้อมูลลงในออบเจ็กต์ SourceBuffer
มากเกินไป (การเพิ่มออบเจ็กต์ SourceBuffer
รายการอื่นๆ ลงในองค์ประกอบMediaSource
หลักอาจทำให้เกิดข้อผิดพลาดนี้ด้วย ซึ่งอยู่นอกขอบเขตของบทความนี้) หาก SourceBuffer
มีข้อมูลมากเกินไป การเรียกใช้ SourceBuffer.appendBuffer()
จะแสดงข้อความต่อไปนี้ในหน้าต่างคอนโซลของ Chrome

สิ่งที่ควรทราบเกี่ยวกับเรื่องนี้มีดังนี้ ก่อนอื่น ให้สังเกตว่าชื่อ QuotaExceededError
ไม่ได้ปรากฏในข้อความ หากต้องการดู ให้ตั้งจุดหยุดชั่วคราวในตำแหน่งที่คุณสามารถจับข้อผิดพลาดและตรวจสอบในหน้าต่างการติดตามหรือขอบเขต เราได้แสดงข้อมูลนี้ไว้ด้านล่าง

ประการที่ 2 คือไม่มีวิธีใดที่แน่ชัดในการดูปริมาณข้อมูลที่ SourceBuffer
รองรับได้
ลักษณะการทํางานในเบราว์เซอร์อื่นๆ
ขณะเขียน Safari ไม่ได้แสดง QuotaExceededError
ในบิลด์หลายรายการ แต่ระบบจะนำเฟรมออกโดยใช้อัลกอริทึมแบบ 2 ขั้นตอน โดยจะหยุดหากมีพื้นที่เพียงพอที่จะรองรับ appendBuffer()
ก่อนอื่น ระบบจะเพิ่มพื้นที่ว่างสำหรับเฟรมจากเวลา 0-30 วินาทีก่อนเวลาปัจจุบันเป็นกลุ่มๆ ละ 30 วินาที จากนั้นจะลบเฟรมเป็นกลุ่มๆ ละ 30 วินาทีจากระยะเวลาย้อนหลังไปจนถึง 30 วินาทีหลังจาก currentTime
อ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในชุดการเปลี่ยนแปลงของ WebKit จากปี 2014
แต่โชคดีที่ 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
มีหลายวิธี แต่ในทางปฏิบัติแล้ว การใช้แนวทางอย่างน้อย 1 วิธีร่วมกันจะดีที่สุด แนวทางของคุณควรอิงตามปริมาณที่คุณดึงข้อมูลและพยายามต่อท้ายนอกเหนือจาก HTMLMediaElement.currentTime
และปรับขนาดนั้นตาม QuotaExceededError
นอกจากนี้ การใช้ไฟล์ Manifest บางประเภท เช่น ไฟล์ mpd (MPEG-DASH) หรือไฟล์ m3u8 (HLS) ยังช่วยให้คุณติดตามข้อมูลที่เพิ่มลงในบัฟเฟอร์ได้อีกด้วย
ต่อไปเรามาดูแนวทางต่างๆ ในการจัดการกับ
QuotaExceededError
- นําข้อมูลที่ไม่จําเป็นออกและต่อท้ายอีกครั้ง
- ต่อท้ายด้วยเศษข้อความขนาดเล็ก
- ลดความละเอียดของการเล่น
แม้ว่าจะใช้ร่วมกันได้ แต่เราจะอธิบายทีละรายการ
นําข้อมูลที่ไม่จําเป็นออกและต่อท้ายอีกครั้ง
จริงๆ แล้วชื่อของการดำเนินการนี้ควรเป็น "นำข้อมูลที่มีโอกาสน้อยที่สุดที่จะใช้งานเร็วๆ นี้ออก แล้วลองเพิ่มข้อมูลที่มีโอกาสที่จะใช้งานเร็วๆ นี้อีกครั้ง" ชื่อยาวเกินไป คุณแค่ต้องจำสิ่งที่ฉันต้องการจะสื่อจริงๆ
การนําข้อมูลล่าสุดออกนั้นไม่ง่ายเหมือนการเรียกใช้ SourceBuffer.remove()
หากต้องการนำข้อมูลจาก SourceBuffer
ออก การตั้งค่าสถานะการอัปเดตต้องเป็นเท็จ หากไม่ใช่ ให้โทรหา SourceBuffer.abort()
ก่อนนำข้อมูลออก
สิ่งที่ควรคำนึงถึงเมื่อเรียกใช้ SourceBuffer.remove()
- การดำเนินการนี้อาจส่งผลเสียต่อการเล่น เช่น หากต้องการให้วิดีโอเล่นซ้ำหรือวนเล่นเร็วๆ นี้ คุณอาจไม่ต้องการนําช่วงต้นของวิดีโอออก ในทํานองเดียวกัน หากคุณหรือผู้ใช้กรอวิดีโอไปยังส่วนที่คุณได้นําข้อมูลออกแล้ว คุณจะต้องเพิ่มข้อมูลนั้นต่อท้ายอีกครั้งเพื่อตอบสนองการกรอ
- นำออกอย่างระมัดระวังที่สุด โปรดระวังการนำกลุ่มเฟรมที่เล่นอยู่ออก โดยเริ่มจากคีย์เฟรมที่หรือก่อน
currentTime
เนื่องจากอาจทำให้การเล่นหยุดชะงัก เว็บแอปอาจต้องแยกวิเคราะห์ข้อมูลดังกล่าวออกจากไบต์สตรีมหากข้อมูลไม่อยู่ในไฟล์ Manifest ไฟล์ Manifest ของสื่อหรือความรู้ของแอปเกี่ยวกับช่วงเวลาของเฟรมหลักในสื่อจะช่วยแนะนำช่วงการนำออกของแอปเพื่อป้องกันการนำสื่อที่เล่นอยู่ออก ไม่ว่าคุณจะนำรูปภาพใดออก โปรดอย่านำกลุ่มรูปภาพที่เล่นอยู่หรือรูปภาพ 2-3 รูปแรกออก โดยทั่วไปแล้ว อย่านำออกเกินเวลาปัจจุบัน เว้นแต่คุณจะมั่นใจว่าไม่จำเป็นต้องใช้สื่อนั้นอีกต่อไป หากนำออกใกล้กับเพลย์เฮด คุณอาจทำให้วิดีโอหยุดชั่วคราว - 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);
ลดความละเอียดของการเล่น
ซึ่งคล้ายกับการนําข้อมูลล่าสุดออกและเพิ่มต่อท้ายอีกครั้ง อันที่จริงแล้ว 2 อย่างนี้อาจทำร่วมกันได้ แต่ตัวอย่างด้านล่างแสดงเฉพาะการลดความละเอียด
สิ่งที่ควรคำนึงถึงเมื่อใช้เทคนิคนี้
- คุณต้องเพิ่มกลุ่มเริ่มต้นใหม่ต่อท้าย คุณต้องดำเนินการนี้ทุกครั้งที่เปลี่ยนตัวแทน กลุ่มเริ่มต้นใหม่ต้องเป็นกลุ่มสื่อที่ตามหลัง
- การประทับเวลาของสื่อที่ต่อท้ายควรตรงกับการประทับเวลาของข้อมูลในบัฟเฟอร์มากที่สุด แต่ต้องไม่ข้ามไปข้างหน้า การซ้อนทับข้อมูลที่บัฟเฟอร์ไว้อาจทำให้ภาพกระตุกหรือหยุดชะงักเป็นช่วงๆ ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ ไม่ว่าคุณจะเพิ่มอะไรต่อท้าย โปรดอย่าวางซ้อนกับเพลย์เฮดเนื่องจากจะทำให้เกิดข้อผิดพลาด
- การกรออาจขัดจังหวะการเล่น คุณอาจต้องการกรอไปยังตำแหน่งที่ต้องการและเล่นต่อจากตรงนั้น โปรดทราบว่าการดำเนินการนี้จะส่งผลให้การเล่นหยุดชะงักจนกว่าการกรอจะเสร็จสมบูรณ์