جاوااسکریپت - چگونه میتوان دادههای جریان را از MediaRecorder (وب) بر اساس حجم به جای زمان دریافت کرد؟


من در حال حاضر از MediaRecorder برای دریافت تکههایی از جریان ویدیو از وبکم/میکروفن کاربر به این صورت استفاده میکنم:

navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then((stream) => {
      var mediaRecorder = new MediaRecorder(stream);
      mediaRecorder.start(5000);

      mediaRecorder.ondataavailable = (blobEvent) => {
        console.log('got 5 seconds of stream', blobEvent);
      }
    })

این هر ۵ ثانیه یک قسمت از جریان ویدیو را پخش میکند، با این حال من میخواهم قسمتها با اندازه خاصی باشند، نه طول مشخص. به نظر نمیرسد راه روشنی برای انجام این کار وجود داشته باشد، زیرا نمیتوانم اندازه قسمت فعلی را بدون شروع قسمت جدید بررسی کنم و بعد از آن هم نمیتوانم آنها را ترکیب کنم. این راهحلی است که من با استفاده از دو ضبطکننده رسانه پیدا کردهام:

  const MIN_BLOB_SIZE = 5000000;
  var partSize = 0;
  navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then((stream) => {
      var mediaRecorder = new MediaRecorder(stream);
      var mediaRecorder2 = new MediaRecorder(stream)
      mediaRecorder.start();
      mediaRecorder2.start(5000)

      mediaRecorder2.ondataavailable = (blobEvent) => {
          console.log('got 5 seconds of data', blobEvent)
          const blob = blobEvent.data
          partSize += blob.size;
          if (partSize >= MIN_BLOB_SIZE) {
              partSize = 0;
              mediaRecorder.requestData();
          }
      }

      mediaRecorder.ondataavailable = (blobEvent) => {
        console.log('got a chunk at least 5mb', blobEvent);
      };
    });

اما این حس میشود که عجولانه است، تکهها را ناصحیح میدهد، نیاز دارد که مطمئن شوم این دو ضبطکننده کاملاً هماهنگ هستند، مدیریت خطا و موارد حاشیهای را پیچیده میکند، و من نگران پیامدهای عملکردی استفاده از دو ضبطکننده رسانه هستم. پاسخی را میپذیرم که این کار را با یک ضبطکننده رسانه انجام دهد، یا اگر فقط با یک امکانپذیر نباشد، اگر کسی بتواند من را قانع کند که استفاده از دو ضبطکننده رسانه از نظر عملکرد اشکالی ندارد، آن را نیز میپذیرم و با مشکلهایی که ایجاد میکند کنار میآیم.

پاسخ شماره ۱

ترکیب تکهها

شما میتوانید بلوکها را بعداً با new Blob(blobArray) ترکیب کنید. اگر واقعاً نیاز دارید که بلوکهایی با اندازه مشخص را پردازش کنید، میتوانید از Blob.slice استفاده کنید. میتواند چیزی شبیه این باشد:

const MIN_BLOB_SIZE = 5000000;
var partSize = 0, parts = [];
navigator.mediaDevices
  .getUserMedia({audio: true, video: true})
  .then((stream) => {
    var mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.start(5000);
    mediaRecorder.ondataavailable = (blobEvent) => {
        console.log('got 5 seconds of data', blobEvent);
        const blob = blobEvent.data;
        partSize += blob.size;
        parts.push(blob);
        if (partSize >= MIN_BLOB_SIZE) {
            let bigBlob = new Blob(parts, { type: blob.type });
            // if the blob size doesn't need to be precise:
            partSize = 0;
            parts = [];
            // do something with bigBlob

            // or if the blob size needs to be precise:
            // let sizedBlob = bigBlob.slice(0, MIN_BLOB_SIZE, blob.type);
            // parts = [ bigBlob.slice(MIN_BLOB_SIZE, bigBlob.size, blob.type) ];
            // partSize = parts[0].size;
            // do something with sizedBlob

        }
    };
    mediaRecorder.onstop = (blobEvent) => {
        console.log('Recording Stopped');
        const blob = blobEvent.data;
        partSize += blob.size;
        parts.push(blob);
        let bigBlob = new Blob(parts, { type: blob.type });
        // do something with bigBlob, which may be smaller than MIN_BLOB_SIZE
    };
});

تنظیم اندازه بلاک با نرخ بیت

شما ممکن است به گزینه bitsPerSecond (و همچنین audioBitsPerSecond و videoBitsPerSecond) در API MediaRecorder نیز علاقهمند باشید، که ممکن است اندازههای blob پیشبینیپذیرتری برای مقدار زمان ضبط شده داده شده به شما بدهد. با این حال، این ممکن است کیفیت ویدئو و صدا را تحت تأثیر قرار دهد.