Изменение качества MediaRecorder и canvas.captureStream?

Недавно я пытался создать видео в браузере и, таким образом, играл с двумя подходами:

Подход whammy работает хорошо, но поддерживается только в Chrome, так как это единственный браузер, который в настоящее время поддерживает кодировку webp (canvas.toDataURL("image/webp")). Поэтому я использую подход captureStream в качестве резервной копии для Firefox (и использую libwebpjs для Сафари).

Итак, теперь на мой вопрос: есть ли способ контролировать качество видео потока холста? А если нет, то рассматривалось ли что-то подобное браузерами/w3c?

Вот скриншот одного из кадров видео, сгенерированного whammy:

использование библиотеки whammy js для объединения кадров webp в видео webm

А вот тот же кадр, сгенерированный подходом MediaRecorder/canvas.captureStream:

используя MediaRecorder и canvas.captureStream

Моя первая мысль — искусственно увеличить разрешение холста, который я транслирую, но я не хочу, чтобы выходное видео было больше.

Я пытался увеличить частоту кадров, передаваемую методу captureStream (думая, что могут происходить какие-то странные интерполяции кадров), но это не помогает. На самом деле это ухудшает качество, если я делаю его слишком высоким. Моя текущая теория заключается в том, что браузер определяет качество потока на основе того, к какой вычислительной мощности он имеет доступ. В этом есть смысл, потому что, если он будет поддерживать заданную мной частоту кадров, то что-то должно уступить.

Итак, следующая мысль состоит в том, что я должен замедлить скорость, с которой я загружаю холст изображениями, а затем пропорционально снизить значение FPS, которое я передаю в captureStream, но проблема в том, что хотя я, вероятно, решил проблему качества, я получил бы видео, которое работает медленнее, чем должно.

Изменить: вот грубый набросок кода, который я использование, если это поможет кому-то в подобной ситуации.


person Community    schedule 17.09.2018    source источник
comment
Можете ли вы поделиться частью своего кода?   -  person Helder Sepulveda    schedule 17.09.2018
comment
Это артефакты сжатия, и боюсь там таких вариантов нет... Так что во-первых, это не из-за captureStream. Вы можете проверить это, передав свой поток напрямую в srcObject videoElement, и вы не заметите столько артефактов. Основная проблема заключается в том, что большинство распространенных видеокодеков не предназначены для отображения такой графики, воспринимайте это как то, что делает JPEG. Существует опция videoBitsPerSecond MediaRecorder, но здесь она, вероятно, не поможет. (Я пытался, и это не так). В Chrome у меня чуть менее ужасные результаты с кодеком vp8, чем с любым другим.   -  person Kaiido    schedule 18.09.2018
comment
@HelderSepu Я пытался удалить ненужные части моего кода, поэтому в нем может быть одна или две ошибки: >gist.github.com/josephrocca/ec073b3a90f936bec87bbd8e3e4c3486   -  person    schedule 18.09.2018
comment
Просто примечание о вашей сути: if(MediaRecorder) должно быть if(window.MediaRecorder), иначе вы выдаете ReferenceError, и вместо цикла setTimeout 1 мс вам лучше запустить запросAnimationFrame один (я не думаю, что вы все равно можете записывать со скоростью более 60 кадров в секунду )   -  person Kaiido    schedule 18.09.2018
comment
Ах, спасибо за MeidiaRecorder улов. Причина, по которой я выбрал setTimeout, а не requestAnimationFrame, заключается в том, что я решил, что последний более склонен к дросселированию браузером в случае задержки - я бы предпочел, чтобы браузер пользователя зависал, чем риск пропуска кадров. Я также не устанавливал тайм-аут на 1/opts.fps, потому что решил, что в идеале я должен обновлять холст намного быстрее, чем частота кадров captureStream, иначе я рискую чем-то вроде эффект временного сглаживания. Хотя могу ошибаться.   -  person    schedule 18.09.2018
comment
setTimeout будет регулироваться так же, как rAF... См. этот вопрос/ответ для альтернативного метода синхронизации, который не должен регулироваться. Но обратите внимание, что это регулирование только для случая, когда окно размыто. Если это происходит из-за того, что браузер занят, даже ваши рисунки на холсте в любом случае будут ограничены.   -  person Kaiido    schedule 19.09.2018
comment
Хорошо, переключил суть на requestAnimationFrame. Я провел несколько тестов, и ни один из подходов, кажется, не регулируется в Chrome или Firefox, когда вкладка/браузер не сфокусированы. Немного смущен этим.   -  person    schedule 19.09.2018


Ответы (1)


Это артефакты сжатия, и вы пока мало что можете сделать...

Видеокодеки созданы в основном с идеей отображения реальных цветов и форм, что немного похоже на JPEG с очень низким качеством. Они также сделают все возможное, чтобы хранить как можно меньше информации между ключевыми кадрами (некоторые используют алгоритм обнаружения движения), чтобы им нужно было хранить меньше данных.

Эти кодеки обычно имеют некоторые настраиваемые параметры, которые позволяют нам улучшить постоянное качество кодирования, но спецификации MediaRecorder не зависят от кодека, они не предоставляют (пока) возможность в API для нас, веб-разработчиков, для установки любых других вариант, чем фиксированный битрейт (который здесь нам больше не поможет).

Существует это предложение, которое требует такой функции.

person Kaiido    schedule 18.09.2018
comment
Спасибо, что изучили это! Приятно видеть, что этот материал обсуждается людьми w3c. - person ; 18.09.2018
comment
Мне любопытно, почему вещи с фиксированным битрейтом (например, videoBitsPerSecond в конструкторе MediaRecorder) здесь не поможет улучшить качество? Разве это не то, что битрейт предназначен для управления? Должно быть, у меня какое-то недоразумение. - person ; 25.02.2019
comment
@Joe, во-первых, нет опции CBR, videoBitsPerSecond - это всего лишь целевая скорость любого режима (я думаю, обычно это VBR). Тогда я предполагаю, что то, что улучшает качество видео в VP8, на самом деле является другим вариантом: webmproject.org/ документы/параметры кодировщика - person Kaiido; 25.02.2019
comment
На самом деле, увеличение videoBitsPerSecond улучшает внешний вид. - person Max; 08.08.2019