передаваемый формат видео getUserMedia / MediaRecorder больше запрошенного. Как сказать?

Фон:

В Windows 10 я использую getUserMedia (gUM) и MediaRecorder в Google Chrome (v71) для захвата и кодирования видеопоток.

  • Я использую параметр constraints для gUM, чтобы сообщить ему, что мне нужен формат видео 352x288.
  • Я запрашиваю video/webm; codecs="avc1.42E01E" в качестве типа MIME закодированного потока (это H.264, заключенный в Matroska).

  • В качестве источника видео я выбираю простенькую веб-камеру, встроенную в ноутбук. Она называется EasyCamera производства DMAX-AVC. Заманчиво назвать это CheezyCamera.

Видеопоток создается нормально.

Проблема:

Размеры закодированного видео в потоке - 440x360, а не запрошенные мной 352x288. Эта информация встроена в записанный поток и видна только потребителю этих данных. Использование различных API-интерфейсов показывает, что метаданные потока gUM, MediaRecorder и <video> элемента считают, что размеры соответствуют тем, которые я просил.

Конечно, веб-камера, gUM и MediaRecorder рассматривают параметр ограничений как предложения и могут свободно ответить чем-то другим. В этом случае они отвечают 440x360, когда я запрашиваю 352x288. Эта система функционирует так, как задумано; это не моя проблема.

Чтобы уточнить, неожиданные размеры 440x360 видны только потребителю записанного потока. Я надеюсь найти способ узнать, что веб-камера производителя, gUM и сигнальная цепочка MediaEncoder производят другое разрешение, чем я просил.

Как потребитель потока узнает размеры потока? Они находятся в блоках Matroska PixelWidth и PixelHeight и встроены в поток H.264. (Как ни странно, учитывая, что это разрешение выбирается программно, это не целое число макроблоков 16x16. Конечно, оно все еще работает.)

Я не могу проанализировать записанные данные в браузере, потому что они хранятся в виде непрозрачных BLOB-объектов.

Когда я использую другую, лучшую веб-камеру (Logitech C615), мой кодированный видеопоток имеет размер, который я запрашивал.

Мой вопрос:

Есть ли способ в цепочке сигналов webcam / gUM / MediaRecorder / <video> найти фактические размеры закодированного потока в браузере, фактически записывающем поток? То есть могу ли я найти ответ цепочки сигналов на мои запрошенные измерения без декодирования сгенерированного потока?


person O. Jones    schedule 24.01.2019    source источник
comment
В ваших высказываниях есть некоторые противоречия: где-то вы говорите, что размеры закодированного видео в потоке равны 440x360, а затем вы говорите, что все потоки, MediaRecorder и элемент видео (то есть потребители потока) говорят, что это тот, который вы просили (352x288). Вы уверены, что не хотели сказать, что неправильные размеры только у записанного файла? Также поясните, пожалуйста, как вы проверяли размеры у этих потребителей. И, наконец, вы пытались воспроизвести из другого медиапотока с такими же размерами? Например, исходящий от холста.   -  person Kaiido    schedule 27.01.2019
comment
Не могли бы вы предоставить образец кода, например, как вы устанавливаете ширину и высоту для своего кодировщика. Если я правильно помню из своего последнего проекта, getUserMedia() пример не гарантирует, что размер видео будет именно тем, который вы запрашиваете, и также зависит от вашего оборудования.   -  person Jimi Pajala    schedule 27.01.2019
comment
Пожалуйста, посмотрите мои правки к моему вопросу. Работаем над <canvas> источником ...   -  person O. Jones    schedule 27.01.2019
comment
Как ни странно, это сгенерированное разрешение не является целым числом макроблоков 16x16 - это нормально и не проблема, оно дополняется до ближайшего кратного, и декодер обрезает его обратно.   -  person aergistal    schedule 31.01.2019


Ответы (3)


Чтобы получить видеодорожку (MediaStreamTrack), затем используйте _ 2_, чтобы получить MediaTrackSettings, который содержит высоту и ширину видео потока.

Поэтому, если я запрашиваю видео с высотой 0, указанной в качестве ограничений, я получаю видео высотой 1 пиксель. Во время потоковой передачи мы можем получить как запрошенную мной высоту, так и высоту, которую я получаю в качестве вывода.

function handleMediaStream(mystream){
  let videoStreamTrack = mystream.getVideoTracks()[0];
  let constraints = videoStreamTrack.getConstraints();
  console.log(constraints.width, constraints.height);
  // outputs: 640 0
  let settings = videoStreamTrack.getSettings();
  console.log(settings.width, settings.height);
  // outputs: 640 1
}

let videoConstraints = { width: 640, height: 0 }
navigator.mediaDevices.getUserMedia({ video: videoConstraints })
.then(function create_media_recorder(mystream) {
  handleMediaStream(mystream);
});
person Munim Munna    schedule 27.01.2019
comment
К сожалению, результат MediaStreamTrack getSettings (а также результаты getCapabilities и getConstraints) показывают запрошенные мной ширину и высоту, а не фактическую ширину и высоту. - person O. Jones; 28.01.2019
comment
Вы уверены в фактической ширине и высоте? Как вы получаете высоту и ширину? - person Munim Munna; 28.01.2019

Возможно, вам потребуется использовать ключевое слово ограничения exact, например, в этот тест

const sdPalConstraints = {
  video: {width: {exact: 352}, height: {exact: 288}}
};
// Assuming |video| exists and represents a <video> element.
navigator.mediaDevices.getUserMedia(sdPalConstraints)
                      .then(stream) => {video.srcObject = stream};

Это не гарантирует, что веб-камера будет транслировать в этом разрешении, но если созданная камера отличается от запрошенной, VideoTrackAdapter будет задействован, чтобы адаптировать его для вас (и для MediaRecorder).

person miguelao    schedule 29.01.2019
comment
Хотел бы я сказать, что это помогло. Но этого не произошло. Вздох. - person O. Jones; 05.02.2019

Попробовав разные вещи, предложенные другими ответившими на этот вопрос, мне не удалось решить эту проблему.

Я пришел к выводу, что это ошибка где-то в цепи сигнала веб-камеры от Google Chrome до gUM.

person O. Jones    schedule 02.02.2019