HTMLImageElement — src как поток

Раньше вы могли использовать URL.createObjectURL() и передавать ему MediaStream. Однако это было удалено (см. https://www.fxsitecompat.dev/en-CA/docs/2017/url-createobjecturl-stream-has-been-deprecated/).

Функциональность замены заключалась в том, чтобы вместо этого использовать HTMLMediaElement.srcObject. Это делает хорошую работу по покрытию видеокейса.

Однако HTMLImageElement не наследуется от HTMLMediaElement. У него также нет srcObject.

В моем конкретном случае я разрабатываю плагин FireFox, который использует функциональность потока фильтра WebRequest для преобразования изображений. С помощью этого API я получаю фрагменты данных ArrayBuffer. Я хотел бы иметь возможность передавать их по мере получения на Image(), который декодирует их на лету, а не просто накапливает их, превращая в BLOB-объект, а затем преобразовывая в URL-адрес через URL.createObjectURL(blob).

Есть ли способ сделать это в потоковом режиме?

(Примечание 1: я согласен с конкретным решением FireFox, если это необходимо.)

(Примечание 2: я попытался установить HTMLVideoElement src, например, в PNG, но оказалось, что элемент видео действительно привередлив и поддерживает только форматы видео, а не неподвижные изображения. Если бы я мог заставить HTMLVideoElement.srcObject загружать неподвижные изображения, это могло бы сделать возможным решение на основе MediaStream. , слишком).


person J Trana    schedule 27.09.2019    source источник
comment
Примечание: в награде указано, что я ищу замену для URL.createObjectURL(blob). Это опечатка, и в ней должно быть указано URL.createObjectURL(MediaStream), как намекает вопрос. Прошу прощения за путаницу.   -  person J Trana    schedule 07.10.2019


Ответы (1)


URL.createObjectURL( MediaStreamInstance ) устарел, а не URL.createObjectURL( BlobInstance ) или другие допустимые входные данные для этого метода (например, MediaSource).

MediaStreams может отображать только видео- и аудиоданные мультимедиа, я не смог найти цитату, где это было сказано точно, но чтение спецификаций делает это довольно ясным, наряду с тем фактом, что MediaStreamTrack.kind может быть только "audio" или "video".

Точно так же, как вы не можете установить <img src="video.mp4">, вы никогда не сможете передать MediaStream в <img>, поэтому для вас это не проблема, и URL.createObjectURL будет работать так, как вы хотите:

const img = document.getElementById( 'img' );
fetch( "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" )
.then( (resp) => resp.arrayBuffer() )
.then( (buf) => {
  const blob = new Blob( [buf], { type: 'image/png' } );
  img.src = URL.createObjectURL( blob );
} );
<img id="img">

Единственный способ получить настоящий поток в <img> — использовать формат MJPEG.


Было решено, что MediaStreams больше нельзя разрешать, потому что слишком часто авторы не отзывали его, когда должны были, а MediaStream, связанный blobURI, нужно было поддерживать в рабочем состоянии, а это означает, что даже аппаратный источник в случае локальный поток должен был поддерживаться в течение всей жизни этого blobURI (что может быть довольно долго в некоторых обстоятельствах).

Когда все основные браузеры, наконец, стали поддерживать свойство MediaElement.srcObject для MediaStreams, сохранять его было мало смысла.

Вот длинное обсуждение репозитория спецификаций.
Вот отчет об ошибке Firefox.
Вот пример Chrome.

(обратите внимание, что единственное, что было удалено, — это возможность сделать так, чтобы <iframe> или <object> указывали на такой MediaStream через blobURI, но нет реального варианта использования их вместо элемента <video>.)

person Kaiido    schedule 06.10.2019
comment
Вы правы в том, что URL.createObjectURL(blob) не устарел - это представляет собой опечатку между моим исходным вопросом и объявлением вознаграждения. Он должен был читать URL.createObjectURL(MediaStream), как вы, вероятно, уже догадались. Цель: как я могу загрузить изображение через потоковую передачу? Разве нельзя было создать URL.createObjectURL(MediaStream) и передать его Image()? - person J Trana; 07.10.2019
comment
Так же, как вы не можете сделать <img src="video.mp4">. Данные, передаваемые из MediaStream в MediaElement, представляют собой видеоданные, img не обеспечивает никакого декодирования видео. Единственный настоящий поток, который вы можете получить для <img>, всегда был и остается через mjpeg. Но это не имеет ничего общего с MediaStream API. - person Kaiido; 07.10.2019
comment
Ну, я не так уверен в этом. <img> также поддерживает форматы анимированных изображений, такие как GIF и APNG. Поэтому мне кажется вполне разумным, что все форматы — анимированные или нет — могли (может быть?) поддерживаться MediaStream, и что <img> накладывает только дополнительные ограничения, например, на. зарегистрированные декодеры. Так, например, возможно, <img> декодирует только JPEG, MJPEG и GIF, но <video> поддерживает MPEG и т. д. - все это использует MediaStream под капотом. Однако я нашел эту ссылку на обсуждение createObjectURL. ... - person J Trana; 07.10.2019
comment
... что оба предоставляют авторитетный источник по крайней мере для части вашего заявления об отзыве, а также демонстрируют явное намерение использовать MediaStream только для аудио- и видеоэлементов. Если вы можете включить это в качестве ссылки в свой ответ (и, если возможно, предоставить источник информации об отзыве блоба), я предоставлю награду, поскольку в ответе есть достоверная информация. Я все еще расстроен тем, что первоначальный вопрос об изображении и потоковой загрузке кажется немного открытым. Я надеялся, что там что-то есть. - person J Trana; 07.10.2019
comment
Ни APNG, ни GIF не являются настоящим потоком, внутри они представляют собой просто последовательность неподвижных изображений, упакованных в один и тот же контейнер с некоторыми метаданными для установки частоты. Декодерам нужен весь файл для воспроизведения анимации => данные не могут передаваться в потоковом режиме. Я отредактирую свой ответ со ссылками на различные намерения для устаревания, когда найду время, и, возможно, для тех, что MediaStream предназначен только для видео мультимедиа (кстати, я не сказал, что MediaStreams предназначены только для MediaElements, другие API также используют его , как WebAudioAPI и WebRTC, я сказал, что его данные — это только аудио/видео). - person Kaiido; 07.10.2019
comment
Хе-хе, видеоконтейнеры не всегда оптимизированы для Интернета; иногда макет оптимизирован для мультиплексора. Но даже в этом случае, если кадр независим, сам кадр может быть декодирован в потоковом режиме, как только станет известно, что он может быть отображен. Должен сказать, что теперь мне очень любопытно посмотреть, как Firefox на самом деле реализует Image.src под капотом. В любом случае, с нетерпением ждем ваших обновлений и спасибо, что нашли время ..! - person J Trana; 07.10.2019
comment
Спасибо за дополнения! Вот награда. Я собираюсь оставить это открытым, чтобы посмотреть, сможет ли кто-нибудь еще придумать какой-нибудь необычный творческий ответ на действие потоковой передачи байтов. - person J Trana; 08.10.2019