เกินโควต้าการบัฟเฟอร์

Joe Medley
Joe Medley

หากใช้ส่วนขยายแหล่งที่มาของสื่อ (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 อย่างนี้อาจทำร่วมกันได้ แต่ตัวอย่างด้านล่างแสดงเฉพาะการลดความละเอียด

สิ่งที่ควรคำนึงถึงเมื่อใช้เทคนิคนี้

  • คุณต้องเพิ่มกลุ่มการเริ่มต้นใหม่ คุณต้องดำเนินการนี้ทุกครั้งที่เปลี่ยนตัวแทน กลุ่มเริ่มต้นใหม่ต้องเป็นกลุ่มสื่อที่ตามหลัง
  • การประทับเวลาของสื่อที่ต่อท้ายควรตรงกับการประทับเวลาของข้อมูลในบัฟเฟอร์มากที่สุด แต่ต้องไม่ข้ามไปข้างหน้า การซ้อนทับข้อมูลที่บัฟเฟอร์ไว้อาจทำให้ภาพกระตุกหรือหยุดชะงักเป็นช่วงๆ ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ ไม่ว่าคุณจะเพิ่มอะไรต่อท้าย โปรดอย่าวางซ้อนกับเพลย์เฮดเนื่องจากจะทำให้เกิดข้อผิดพลาด
  • การกรออาจขัดจังหวะการเล่น คุณอาจต้องการกรอไปยังตำแหน่งที่ต้องการและเล่นต่อจากตรงนั้น โปรดทราบว่าการดำเนินการนี้จะทำให้การเล่นหยุดชะงัก จนกว่าการกรอวิดีโอจะเสร็จสิ้น