Синхронизация данных с видео с помощью WebRTC
Я использую WebRTC
для отправки видео с сервера на браузер клиента (используя собственный WebRTC API
и MCU WebRTC
сервер, например Kurento).
Прежде чем отправлять его клиентам, каждый кадр видео содержит метаданные (например, субтитры или любой другой аппликативный контент). Я ищу способ отправить эти метаданные клиенту, чтобы он оставался синхронизированным (до момента его фактического представления). Кроме того, я хотел бы иметь доступ к этим данным со стороны клиента (по Javascript).
Некоторые варианты, о которых я думал:
- Отправка данных с помощью WebRTC DataChannel. Но я не знаю, как обеспечить синхронизацию данных по каждому кадру. Но я не мог найти способ обеспечить передачу данных по каналу данных и синхронизацию видеоканала (опять же, я надеюсь получить точный уровень одиночного кадра).
- Отправка данных вручную клиенту в некотором роде (WebRTC DataChannel, websockets и т.д.) с отметками времени, которые соответствуют отметкам времени видео. Однако, даже если Kurento или другие средние серверы сохраняют информацию о отметке времени в видео, согласно следующему ответу, нет подходящего способа получить метки времени видео из javascript:
Как использовать API Javascript WebRTC для доступа к исходящей звуковой метке RTP в отправителе и временной отметке времени RTP в приемнике?. Я думал об использовании стандартного видеоэлемента
timeupdate
, но я не знаю, будет ли он работать для точного уровня кадра, и я не уверен, что это значит в реальном видео, как в WebRTC.
- Отправка данных вручную и присоединение к видео в качестве другого
TextTrack
. Затем используйте onenter
и onexit
, чтобы прочитать его синхронно: http://www.html5rocks.com/en/tutorials/track/basics/. Он по-прежнему требует точных временных меток, и я не уверен, как узнать, какие временные метки и если Куренто передает их как есть.
- Используя API статистики WebRTC для ручного подсчета кадров (используя
getstats
) и надейтесь, что информация, предоставленная этим API, будет точной.
Каков наилучший способ сделать это и как решить проблемы, о которых я упомянул в любом случае?
EDIT: Требуется точная синхронизация (с разрешением не более одного кадра) метаданных с соответствующим фреймом.
Ответы
Ответ 1
Я подозреваю, что количество данных на кадр довольно мало. Я бы посмотрел на его кодирование в 2D-штрих-код и поместил его в каждый кадр таким образом, чтобы он не удалялся сжатием. Или просто кодируйте временную метку, как это.
Затем на стороне игрока вы просматриваете изображение в определенном кадре и извлекаете данные или, если хотите,
Ответ 2
Хорошо, сначала давайте получим видео и аудио с помощью getUserMedia и дадим исходные данные с помощью
https://github.com/streamproc/MediaStreamRecorder
:
/*
*
* Video Streamer
*
*/
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script>
<script>
// FIREFOX
var mediaConstraints = {
audio: !!navigator.mozGetUserMedia, // don't forget audio!
video: true // don't forget video!
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var mediaRecorder = new MediaStreamRecorder(stream);
mediaRecorder.mimeType = 'video/webm';
mediaRecorder.ondataavailable = function (blob) {
// POST/PUT "Blob" using FormData/XHR2
};
mediaRecorder.start(3000);
}
function onMediaError(e) {
console.error('media error', e);
}
</script>
// CHROME
var mediaConstraints = {
audio: true,
video: true
};
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
function onMediaSuccess(stream) {
var multiStreamRecorder = new MultiStreamRecorder(stream);
multiStreamRecorder.video = yourVideoElement; // to get maximum accuracy
multiStreamRecorder.audioChannels = 1;
multiStreamRecorder.ondataavailable = function (blobs) {
// blobs.audio
// blobs.video
};
multiStreamRecorder.start(3000);
}
function onMediaError(e) {
console.error('media error', e);
}
Теперь вы можете отправить данные через DataChannels и добавить свои метаданные в стороне получателя:
/*
*
* Video Receiver
*
*/
var ms = new MediaSource();
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(ms);
ms.addEventListener('sourceopen', function(e) {
var sourceBuffer = ms.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
sourceBuffer.appendBuffer(/* Video chunks here */);
}, false);