Наше расширение записи экрана chrome позволяет пользователю записывать свой экран с помощью getDisplayMedia API, который возвращает поток, который подается в MediaRecorder API.
Обычно мы записываем этот поток с помощью видео контейнера webm с новым кодом vp9 c вот так:
const mediaRecorder = new MediaRecorder(mediaStream, {
mimeType: "video/webm; codecs=vp9"
});
Однако Safari не поддерживает контейнер webm и не поддерживает декодирование код vp9 c. Поскольку MediaRecorder API в Chrome поддерживает только запись в контейнере webm, но поддерживает кодировку h264 (которую может декодировать Safari), вместо этого мы записываем код h264 c в контейнер webm:
const mediaRecorder = new MediaRecorder(mediaStream, {
mimeType: "video/webm; codecs=h264"
});
Это хорошо работает по двум причинам:
поскольку наше приложение для записи является расширением chrome, мы не возражаем, что оно может записывать только в Chrome
поскольку видеоданные закодированы как h264, теперь мы можем почти мгновенно переместить видеоданные в контейнер .mp4, позволяя зрителям Safari просматривать эти записанные видео, не дожидаясь дорогостоящего процесса перекодирования ( обратите внимание, что вы можете просматривать видео без расширения chrome в обычном веб-приложении)
Однако, поскольку API устройства записи мультимедиа не имеет метода для получения продолжительности видеопотока записано до сих пор, и измерение вручную с помощью performance.now
оказалось неточным (с ошибкой от 25 мс до 150 мс), нам пришлось перейти на подачу данных регистратора int oa MediaSource, чтобы мы могли использовать mediaSourceBuffer.buffered.end(sourceBuffer.buffered.length - 1) * 1000
API для получения 100% точного чтения продолжительности записанного видеопотока (в миллисекундах).
Проблема в том, что по какой-то причине MediaSource не может создать экземпляр когда мы используем наш "video / webm; codecs = h264 "MIME-тип.
Выполнение этого:
mediaSourceBuffer = mediaSource.addSourceBuffer("video/webm; codecs=h264");
Результат:
Failed to execute 'addSourceBuffer' on 'MediaSource': The type provided ('video/webm; codecs=h264') is unsupported.
Почему тип MIME поддерживается MediaRecorder, но не MediaSource? Поскольку они принадлежат к одному семейству API, разве они не должны поддерживать одни и те же типы mime? Как мы можем записывать с кодом h264 c при передаче данных в MediaSource с помощью addSourceBuffer?
Единственное решение, которое мы На данный момент можно придумать 2 устройства записи мультимедиа, одну запись в vp9, чтобы мы могли считывать точную продолжительность видео, записанного на данный момент с помощью buffered.end
API, и одну запись в формате h264, чтобы мы могли немедленно переместить видеоданные в контейнер mp4 без необходимости перекодировать код c из vp9 в h264 для пользователей Safari. Однако это было бы очень неэффективно, так как эффективно удерживало бы вдвое больше данных в ОЗУ.
Случаи воспроизведения / codeandbox examples
- vp9 example (оба работают)
- h264 example (медиа-рекордер работает, медиа исходник нет)