หากใช้ส่วนขยายแหล่งที่มาของสื่อ (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
โชคดีที่ 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
มีหลายวิธี แต่ในทางปฏิบัติแล้ว การใช้แนวทางอย่างน้อย 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 อย่างนี้อาจทำร่วมกันได้ แต่ตัวอย่างด้านล่างแสดงเฉพาะการลดความละเอียด
สิ่งที่ควรคำนึงถึงเมื่อใช้เทคนิคนี้
- คุณต้องเพิ่มกลุ่มการเริ่มต้นใหม่ คุณต้องดำเนินการนี้ทุกครั้งที่เปลี่ยนตัวแทน กลุ่มเริ่มต้นใหม่ต้องเป็นกลุ่มสื่อที่ตามหลัง
- การประทับเวลาของสื่อที่ต่อท้ายควรตรงกับการประทับเวลาของข้อมูลในบัฟเฟอร์มากที่สุด แต่ต้องไม่ข้ามไปข้างหน้า การซ้อนทับข้อมูลที่บัฟเฟอร์ไว้อาจทำให้ภาพกระตุกหรือหยุดชะงักเป็นช่วงๆ ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ ไม่ว่าคุณจะเพิ่มอะไรต่อท้าย โปรดอย่าวางซ้อนกับเพลย์เฮดเนื่องจากจะทำให้เกิดข้อผิดพลาด
- การกรออาจขัดจังหวะการเล่น คุณอาจต้องการกรอไปยังตำแหน่งที่ต้องการและเล่นต่อจากตรงนั้น โปรดทราบว่าการดำเนินการนี้จะทำให้การเล่นหยุดชะงัก จนกว่าการกรอวิดีโอจะเสร็จสิ้น