Mediarecorder api не поддерживается или отключен включите этот api или используйте другой браузер
В качестве упражнения в изучении WebRTC я пытаюсь показать локальную веб-камеру и одновременно с отложенным воспроизведением веб-камеры. Чтобы достичь этого, я пытаюсь передать записанные капли в BufferSource и использовать соответствующий MediaSource в качестве источника для элемента видео.
Когда я запускаю это в Chromium 78, я получаю NotSupportedError: Failed to load because no supported source was found. от play элемента видео.
Я понятия не имею, что я делаю не так и как действовать на данном этапе.
Речь идет о чем-то похожем, но мне это не помогает: MediaSource останавливает видео случайным образом
Заставить его работать в Firefox и Chrome очень просто: вам просто нужно добавить аудиокодек в свой список кодеков! video/webm;codecs=opus,vp8
Android должен работать, если работает Chrome
iOS не поддерживает расширения источников мультимедиа, поэтому они SourceBuffer не определены в iOS, и все решение не будет работать.
Глядя на опубликованный вами JSFiddle, одно быстрое исправление, прежде чем мы начнем:
- Вы ссылаетесь на переменную, errorMsgElement которая никогда не определяется. Вы должны добавить на страницу с соответствующим идентификатором, а затем создать const errorMsgElement = document.querySelector(. ) строку для его захвата.
Теперь при работе с Media Source Extensions и MediaRecorder следует отметить, что поддержка будет сильно отличаться в зависимости от браузера. Несмотря на то, что это «стандартизованная» часть спецификации HTML5, она не очень согласована между платформами. По моему опыту, заставить MediaRecorder работать в Firefox не нужно слишком много усилий, заставить его работать в Chrome немного сложнее, заставить его работать в Safari чертовски почти невозможно, а заставить его работать на iOS буквально нет то, что вы можете сделать.
Я прошел и отладил это для каждого браузера и записал свои шаги, чтобы вы могли понять некоторые инструменты, доступные вам при отладке проблем с мультимедиа.
Fire Fox
Когда я проверил ваш JSFiddle в Firefox, я увидел в консоли следующую ошибку:
NotSupportedError: An audio track cannot be recorded: video/webm;codecs=vp8 indicates an unsupported codec
Я помню, что VP8 / VP9 были большим толчком Google и поэтому могут не работать в Firefox, поэтому я попытался внести одну небольшую поправку в ваш код. Я удалил , options) параметр из вашего вызова new MediaRecorder() . Это говорит браузеру использовать любой кодек, который он хочет, поэтому вы, вероятно, получите разный вывод в каждом браузере (но он должен, по крайней мере, работать в каждом браузере).
Это сработало в Firefox, поэтому я проверил Chrome.
На этот раз у меня появилась новая ошибка:
Итак, я перешел к chrome: // media-internals / в своем браузере и увидел следующее:
Audio stream codec opus doesn't match SourceBuffer codecs.
В вашем коде вы указываете видеокодек (VP9 или VP8), но не аудиокодек, поэтому MediaRecorder позволяет браузеру выбирать любой аудиокодек, который он хочет. Похоже, что в Chrome MediaRecorder по умолчанию выбирает "opus" в качестве аудиокодека, но SourceBuffer Chrome по умолчанию выбирает что-то другое. Это было тривиально исправлено. Я обновил ваши две строки, которые установили options.mimeType так:
Поскольку вы используете один и тот же options объект для объявления MediaRecorder и SourceBuffer, добавление аудиокодека в список означает, что SourceBuffer теперь объявляется с допустимым аудиокодеком и воспроизводится видео.
На всякий случай я протестировал новый код (с аудиокодеком) в Firefox. Это сработало! Итак, мы 2 из 2, просто добавив аудиокодек в options список (и оставив его в параметрах для объявления MediaRecorder)
Похоже, что VP8 и opus работают в Firefox, но не по умолчанию (хотя, в отличие от Chrome, значения по умолчанию для MediaRecorder и SourceBuffer одинаковы, поэтому удаление options параметра полностью сработало)
Сафари
Unhandled Promise Rejection: ReferenceError: Can't find variable: MediaRecorder
Первое, что я сделал, это Google "Safari MediaRecorder", который нашел эту статью . Я подумал, что попробую, поэтому посмотрел. Конечно же:
Я щелкнул по нему, чтобы включить MediaRecorder, и в консоли увидел следующее:
Unhandled Promise Rejection: TypeError: MediaRecorder.isTypeSupported is not a function. (In 'MediaRecorder.isTypeSupported(options.mimeType)', 'MediaRecorder.isTypeSupported' is undefined)
Так что у Safari нет isTypeSupported метода. Не волнуйтесь, мы просто скажем: «Если этого метода не существует, предположите, что это Safari, и установите соответствующий тип».
Теперь мне просто нужно было найти mimeType, поддерживаемый Safari. Небольшой поиск в Google предполагает, что поддерживается H.264, поэтому я попробовал:
Это успешно дало мне MediaRecorder started , но не удалось в строке addSourceBuffer с новой ошибкой:
NotSupportedError: The operation is not supported.
Я буду продолжать пытаться диагностировать, как заставить это работать в Safari, но пока я, по крайней мере, обращаюсь к Firefox и Chrome.
Я продолжал работать над Safari. К сожалению, Safari не хватает инструментов Chrome и Firefox для глубокого проникновения во внутреннее устройство мультимедиа, поэтому приходится много гадать.
- Может быть, добавить исходный буфер перед play вызовом видео
- Возможно, добавьте исходный буфер до того, как медиа-источник будет прикреплен к видеоэлементу.
- Возможно добавить исходный буфер с разными кодеками
- так далее
Хотя ошибки консоли теперь исчезли, я все еще не вижу видео. Так что еще есть над чем поработать.
Дальнейшее исследование отладчика в Safari (установка нескольких точек останова и проверка переменных на каждом этапе процесса) обнаружило, handleDataAvailable что в Safari он никогда не вызывался. Похоже, что Firefox и Chrome mediaRecorder.start(100) будут правильно следовать спецификации и вызывать ondatavailable каждые 100 миллисекунд, но Safari игнорирует параметр и буферизует все в один массивный Blob. Вызов mediaRecorder.stop() вручную вызвал ondataavailable вызов со всем, что было записано до этого момента
Я пробовал использовать setInterval для вызова mediaRecorder.requestData() каждые 100 миллисекунд, но requestData не был определен в Safari (как isTypeSupported не было определено). Это поставило меня в затруднительное положение.
Затем я попытался очистить весь объект MediaRecorder и создать новый каждые 100 миллисекунд, но это вызвало ошибку в строке await bufferedBlob.arrayBuffer() . Я все еще пытаюсь понять, почему тот потерпел неудачу
Одна вещь, которую я помню о формате MP4, заключается в том, что атом «moov» требуется для воспроизведения любого контента. Вот почему вы не можете загрузить среднюю половину файла MP4 и воспроизвести ее. Вам нужно скачать ВЕСЬ файл. Поэтому я подумал, не является ли тот факт, что я выбрал MP4, причиной того, что я не получаю регулярных обновлений.
Я попытался изменить video/mp4 несколько значений и получил разные результаты:
- video/webm - Операция не поддерживается
- video/x-m4v - Вёл себя как MP4, я получал данные только при .stop() вызове
- video/3gpp - Вёл себя как MP4
- video/flv - Операция не поддерживается
- video/mpeg - Вёл себя как MP4
Все, что ведет себя как MP4, заставило меня проверить данные, которые на самом деле передавались handleDataAvailable . Вот тогда я заметил это:
Независимо от того, какой формат видео я выбрал, Safari всегда давал мне MP4!
Внезапно я вспомнил, почему Safari был таким кошмаром и почему я мысленно классифицировал его как «чертовски почти невозможно». Чтобы сшить вместе несколько MP4, потребуется преобразователь JavaScript.
Тогда я вспомнил, что делал именно это раньше . Я работал с MediaRecorder и SourceBuffer чуть больше года назад, чтобы попытаться создать проигрыватель JavaScript RTMP. После того, как проигрыватель был готов, я хотел добавить поддержку DVR (возврат к частям видео, которое уже было передано в потоковом режиме), что я сделал, используя MediaRecorder и сохранив кольцевой буфер в памяти для 1-секундных видеоблотов. В Safari я запускал эти видеоблобы через преобразователь, который я закодировал, чтобы преобразовать их из MP4 в ISO-BMFF, чтобы я мог объединить их вместе.
Я хотел бы поделиться кодом с вами, но все он принадлежит моему старому работодателю, поэтому на данный момент решение для меня потеряно. Я знаю, что кто-то столкнулся с проблемой компиляции FFMPEG в JavaScript с помощью emscripten, так что вы можете воспользоваться этим.
MediaStream Recording API, иногда просто называемый Media Recording API или MediaRecorder API, тесно связан с Media Capture and Streams API и WebRTC API. MediaStream Recording API делает возможным захват данных, сгенерированных MediaStream или HTMLMediaElement объектом для анализа, обработки или сохранения на дисковое пространство. С ним так же удивительно легко работать.
Базовая концепция
MediaStream Recording API состоит из единого интерфейса, MediaRecorder , который делает всю работу, принимая данные из MediaStream и доставляя их обработчику. Данные поставляются с помощью серии dataavailable событий, уже в том формате, который был указан, когда MediaRecorder был создан. Процесс записи потока прост:
- Установите MediaStream или HTMLMediaElement (в виде или элемента), чтобы тот служил в качестве источника медиа-данных.
- Установите MediaRecorder.ondataavailable обработчик событий для dataavailable событий; он будет вызываться каждый раз, как данные будут доступны.
- Создайте MediaRecorder объект, указав исходный поток и любые опции по желанию (такие как MIME-тип контейнера или желаемый битрейт его треков).
- Как только исходная медиа запустится и будет достигнута точка, где вы будете готовы записать видео, вызовите MediaRecorder.start() для начала записи.
- Ваш dataavailable обработчик будет вызываться каждый раз, как появляются данные, готовые для выполнения вами над ними ожидаемых операций; событие имеет дата-атрибут, чьё значение Blob , который содержит медиа-данные. Вы можете принудительно вызвать dataavailable событие, доставляя тем самым последние данные, чтобы вы могли отфильтровать их, сохранить и тд.
- Запись останавливается автоматически, когда исходное медиа закончит проигрываться.
- Вы можете остановить запись в любое время, вызвав MediaRecorder.stop() (en-US).
Вы можете так же использовать свойства MediaRecorder объекта для определения состояния процесса записи и его pause() (en-US) и resume() (en-US) методы, чтобы остановить и возобновить запись исходной медиа.
Если вам нужно или вы хотите проверить, поддерживается ли определённый MIME-тип, это так же возможно. Просто вызовите MediaRecorder.isMimeTypeSupported() .
Чтобы узнать больше о MediaStream Recording API, смотрите Using the MediaStream Recording API, который показывает, как использовать API для записи аудио клипов. Другая статья, Recording a media element, описывает, как получить поток из или элементов и использовать захватывающие потоки (в этом случае, запись и сохранение их на локальный диск).
The MediaRecorder это интерфейс MediaStream Recording API представляющий функциональность для простой записи медиа. Создаётся с использованием MediaRecorder() конструктора.
Конструктор
MediaRecorder() Создаёт новый объект MediaRecorder , получающий MediaStream для записи. Доступны такие параметры, как установка типа MIME контейнера ( "video/webm","video/mp4" и другие) и скорости передачи аудио-и видеодорожек или одной общей скорости.
Свойства
MediaRecorder.mimeType (en-US) Только для чтения Возвращает тип MIME, который был выбран в качестве контейнера записи для объекта MediaRecorder при его создании. MediaRecorder.state Только для чтения Возвращает текущее состояние объекта MediaRecorder ( inactive , recording , или paused .) MediaRecorder.stream (en-US) Только для чтения Возвращает поток который был передан конструктору при создании объекта MediaRecorder MediaRecorder.ignoreMutedMedia Показывает записывает ли MediaRecorder дорожку MediaStreamTrack если она отключена. Если атрибут равен false, MediaRecorder будет записывать тишину для аудио и чёрные кадры для видео. По умолчанию равно false MediaRecorder.videoBitsPerSecond (en-US) Только для чтения Возвращает скорость кодирования видео. Она может отличаться от скорости, определённой в конструкторе (если была предоставлена). MediaRecorder.audioBitsPerSecond; Только для чтения Возвращает скорость кодирования аудио. Она может отличаться от скорости, определённой в конструкторе (если была предоставлена).
Методы
MediaRecorder.isTypeSupported() (en-US) Возвращает Boolean (en-US) значение показывающее поддерживается ли MIME тип текущим user agent. MediaRecorder.pause() (en-US) Приостанавливает запись медиа. MediaRecorder.requestData() Запрашивает Blob содержащий сохранённые данные полученные с начала записи (или с последнего вызова requestData() ). После вызова этого метода, запись продолжается, но в новый Blob. MediaRecorder.resume() (en-US) Возобновляет запись медиа после паузы. MediaRecorder.start() Начинает запись медиа. В этот метод можно передать аргумент timeslice со значением в миллисекундах. Если он определён, то медиа будет записываться в отдельные блоки заданной продолжительности, вместо записи в один большой блок. MediaRecorder.stop() (en-US) Останавливает запись, после чего запускается событие dataavailable , содержащее последний Blob сохранённых данных.
Обработчики событий
MediaRecorder.ondataavailable Вызывает обработчик dataavailable события, которое запускается раз в timeslice миллисекунд (или, если timeslice не был задан - по окончанию записи). Событие типа BlobEvent (en-US), сдержит записанное медиа в data (en-US). Вы можете использовать обработчик для сбора и других действий в зависимости от полученных данных. MediaRecorder.onerror (en-US) event handler вызывается для обработки события recordingerror , включающего отчёт об ошибках во время записи. Это фатальные ошибки, приводящие к остановке записи. Полученное событие основано на интерфейсе MediaRecorderErrorEvent (en-US), свойство которого error (en-US) содержит DOMException (en-US) описывающие произошедшие ошибки. MediaRecorder.onpause (en-US) event handler вызывается для обработки события pause (en-US) , случившегося во время приостановки медиа. MediaRecorder.onresume (en-US) event handler вызывается для обработки события resume , случившегося во время возобновления записи. MediaRecorder.onstart (en-US) event handler вызывается для обработки события start , случившегося во время начала записи. MediaRecorder.onstop (en-US) event handler вызывается для обработки события stop , случившегося во время завершения записи, а так же при окончании MediaStream — или после вызова MediaRecorder.stop() (en-US)
Пример
Код выше был взят из демо Web Dictaphone. Некоторые строчки были пропущены для краткости. Полный код смотрите здесь
Интерфейс MediaStream Recording позволяет записывать аудио и видео потоки. При использовании с методом navigator.mediaDevices.getUserMedia() , предлагает простой способ записи данных с устройств пользователя, и немедленное их использование в веб приложениях.И аудио и видео могут быть записаны вместе или по отдельности.Цель данной статьи - предоставить базовое руководство о том как использовать объект MediaRecorder , реализующий такой программный интерфейс.
Пример приложения: Веб диктофон
Для демонстрации основной функциональности интерфейса MediaRecorder API , мы создали веб диктофон, позволяющий записывать отрывки аудио и проигрывать их после записи. Он визуализирует устройства ввода звука, используя интерфейс Web Audio API . В этой статье будем концентрироваться на функциональности записи и воспроизведения.
CSS плюшки
Разметка HTML довольно проста, поэтому не будем её рассматривать подробно, но есть более интересные места в CSS, которые стоило бы отметить, и о которых поговорим ниже. Если вам не интересна тема CSS , и хотите сразу приступить к JavaScript, то перейдите к части основных настроек приложения Basic app setup.
Сохраняйте интерфейс ограниченным областью просмотра, независимо от высоты устройства, с функцией calc()
Функция calc одна из полезных утилит возникших в CSS, которая не выглядеть чем-то выдающимся, но вскоре заставит вас думать о том, почему вы не использовали её раньше?; и почему CSS2 макет такой неуклюжий? Она позволяет выполнять вычисления для определения значений из различных CSS единиц измерений, смешивая их в процессе вычисления.
К примеру, в приложении веб диктофона мы создали три области интерфейса, расположенные вертикально. Первые две имеют фиксированную высоту (заголовок и элементы управления):
Третья область (содержащая записываемые образцы, которые можно воспроизвести) должна занимать оставшуюся от первых двух область, независимо от высоты устройства пользователя. Задача может быть решена, установкой высоты третьей области равной 100% родительской высоты, минус высоты и отступы первых двух.
Примечание : Функция calc() имеет хорошую поддержку среди современных браузеров, даже в устаревшем Internet Explorer 9.
Хак чекбокса для отображение/скрытия
Затем скрываем настоящий чекбокс, избегая неразберихи в интерфейсе :
Наконец определяем правило при нажатии чекбокса . Когда он выбран (когда нажат элемент label ) соседний элемент получит значение горизонтального перехода и переместится в представление:
Основные настройки приложения
Для получения медиапотока, который нужно захватить используется метод getUserMedia() . Затем используется интерфейс MediaRecorder , для записи потока и вывода каждого отрывка записи в атрибут элемента для воспроизведения.
Объявим некоторые переменные для кнопок начала записи и остановки, а так же элемент , который будет содержать аудио плееры:
Наконец, для этого раздела создадим базовую структуру getUserMedia :
Все обёрнуто в условный тест, проверяющий поддержку getUserMedia до запуска чего нибудь. Затем вызываем getUserMedia() и внутри определяем:
- Ограничения : Приложению нужен только аудиопоток .
- Функция успешного вызова: Запускается при успешном получении потока функцией getUserMedia .
- Функция обработки ошибок: Если функция getUserMedia по какой либо причине завершиться с ошибкой.
Примечание : Весь код ниже помещается внутрь функции успешного вызова getUserMedia.
Захват медиа потока
Как только функция getUserMedia успешно получила медиапоток, создаём новый объект типа Media Recorder конструктором MediaRecorder() и передаём ему поток, полученный функцией. Это точка входа использования интерфейса MediaRecorder — теперь поток готов для захвата и упаковки в объект Blob , в формате по умолчанию, установленного для браузера.
Существуют несколько методов объекта MediaRecorder , позволяющие контролировать запись медиапотока; в приложении веб диктофон используется два и прослушиваем некоторые события. Прежде всего используем метод MediaRecorder.start() , для запуска записи потока, после нажатия кнопки старта:
Когда объект MediaRecorder приступает к записи его свойство MediaRecorder.state получает значение " recording ".
По мере записи, нам нужно получать аудио данные. Для этого регистрируем обработчик события mediaRecorder.ondataavailable :
Примечание : Браузер будет запускать события dataavailable по необходимости (когда внутренний буфер объекта будет переполняться), но если разработчику нужно вмешаться, в вызов метода start() можно включить параметр timeslice , определяющий диапазон захвата в миллисекундах — к примеру, start(10000) , или вызывать функцию запроса данных MediaRecorder.requestData() , запуская событие по необходимости.
Наконец используем метод MediaRecorder.stop() (en-US) при нажатии кнопки остановки записи и завершения упаковки объекта Blob для его использования в приложении.
Обратите внимание, что запись потока может остановиться естественно, если медиапоток кончился(к примеру, если захватывается музыкальный трек и он кончился, или пользователь отключил использование микрофона, чей поток захватывается).
Получение и использования объекта blob
Когда запись останавливается, свойство state получает значение " inactive ", и запускается событие stop . Мы устанавливаем обработчик этого события, используя свойство mediaRecorder.onstop (en-US), завершая запись всех полученных порций объекта blob на момент остановки:
Пройдём весь код выше и посмотрим, что он делает.
Сначала отображаем пользователю диалог с запросом имени будущей записи.
Затем создаём структуру HTML , вставляя её в контейнер, представляющийся элементом .
После этого создаём объект Blob с комбинацией наших записанных частей аудио и создаём объект URL ссылающийся на него, используя метод window.URL.createObjectURL(blob) . Затем устанавливаем значение атрибута src элемента в созданный объект URL, так, что бы при нажатии на кнопку воспроизведения объект Blob передал свои данные элементу.
Наконец, устанавливаем обработчик события onclick на кнопке удаления, для удаления всей структуры HTML проигрывания результата записи (элемент clip).
The mediarecorder-api tag has no usage guidance.
How to fix err_request_range_not_satisfiable error which occurs when I try to view a video recorded on the browser?
I am new to react and I am trying to develop a web application with video recording capabilities. This is my code: App.js: import ScreenRecording from './Recorder' function App() < return (
How to implement a VU meter to test microphone using MediaRecorder API
I am using the MediaRecorder API (javascript) to record video and audio from users, but when the user choose an audio source (an external microphone for example) I want to display a VU meter kind of .
Flip or Edit MediaStream Api blobs
react-media-recorder not Stopping recording in deployment
I am using react-media-recorder to record audio. It works fine on localhost but when deployed to a server and accessed, the onStop method stops working. It doesn't get invoked. this is my file: import .
Has anyone used the Screen Capture API and getDisplayMedia multiple times? Can we cache the user's grant of permission?
it seems like the standardized way to capture an area of the screen is to use the Screen Capture API and getUserMedia(). We are trying to capture an iframe or video playing a live stream. So we want .
How can I use MediaRecorder API of browser in react native
I just want to use media recorder API to record the stream which I'm using in WebRtc for react-native. Actually I want to save the stream to a file on the backend server. and hence i need to send the .
Is there any way (even if a hack-ish one, and working only on 1-2 main browsers) to impact keyframe interval for MediaRecorder()?
I am building the app along the lines of this: MediaSource randomly stops video and it works fine, except if the client connects to the stream while it was already running, it tooks a lot of time .
How to record webcam with an overlay in javascript?
I am trying to record a user's webcam video with an overlay. I have used MediaStream Recording API and I am able to capture webcam video and audio perfectly of the user using getUserMedia but it shows .
How to upload video recorded with MediaRecorder API using PHP?
I am working on a video recording task using MediaRecorder API. As from frontend I can start the webcam, record video, play the recorded video and download the video. But when I try to upload the .
Possibility to record playback of browser audio element using JavaScript?
I am currently working on a simple audio project which uses HTML / JS audio elements to play audio using buttons. Is it somehow possible to record that audio being played instead of recording the .
Get ReadableStream from Webcam in Browser
I would like to get webcam input as a ReadableStream in the browser to pipe to a WritableStream. I have tried using the MediaRecorder API, but that stream is chunked into separate blobs while I would .
How to record video on Safari iOS using MediaRecorder
I am making a video recording website, and using the recordRTC package, I have it working on chrome desktop and android. However, this package does not work on safari either on desktop or iOS. I have .
Google meet streaming through MediaRecorder APIs
I am trying to record google meet audio and video using getDisplayMedia using media options.I am able to record my screen through getDisplayMedia but unable to record voice coming in google meet. How .
Recording google meet through Webrtc
I am trying to record google meet audio and video using webRtc. I found mediaRecorder Api for same. But i am unable to record meeting, as it is only capturing my webcam and audio. How can i record a .
Adding audio to an incoming stream during video call to record voice of both parties in a call
I have created an app using peer js to initiate video calls. I am using mediarecorder Api to record the incoming stream from caller. However, I need to add audio of both the caller and receiver in the .
Читайте также: