JS перехватывает первый кадр видео

JavaScript
JS перехватывает первый кадр видео

Продолжение предыдущей статьиjs предварительный просмотр изображения/видео — URL.createObjectURL()

Когда видео можно просмотреть и загрузить, необходимо сделать скриншот первого кадра видео и вставить его. Что делать, если первый кадр черный? Следующий кадр.


2020-6-12 Обновление:

По вопросу в сообщении сегодня попробовал еще раз и обнаружил, что под тем же кодом браузеры типа IE/Firefox нормально перехватывают, а вот Google Chrome лиvideoКаким методом или куда добавить таймер, захваченный "первый кадр" - черный экран;

Решение:

  1. существуетvideoдобавить на ярлыкautoplayа такжеmutedАтрибут (один из них обязателен, а также является ограничением по умолчанию Google Chrome), то есть он будет воспроизводиться молча сразу после загрузки, и его можно будет успешно перехватить;
  2. существуетvideoдобавить на ярлыкpreloadАтрибуты.

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


Оригинальный текст ниже:

1. Загрузка файла

использовать<input type="file">загрузить,changeсобытие в качестве превьюvideoизsrcусловие срабатывания Свежий источник:

<video controls width="700" height="300" src="" id="video"></video>
<input type="file" id="input" hidden />
<button id="fileBtn">点击上传视频</button>

Во-вторых, скриншоты холста

О захвате или обработке изображений/видео/текстовых редакторов,canvasЭто очень хороший выбор.

  1. Создать холстcanvasили вhtmlпишите прямо в.
var canvas = document.createElement('canvas');
  1. Создать на основеcanvasсреда рисования
var ctx = canvas.getContext('2d');

С вопросами и ответами:

  • Что такое среда рисования?

В сети принято понимать, что «после подготовки холста требуется некоторая подготовка «красок, кистей, инструментов для рисования». Более официальное слово - вернутьсяcanvasконтекст, Говоря человеческим языком, вы можете лучше управлять своимcanvas'.

  • оgetContext('2d')параметры

в методе2dПараметр в настоящее время можно понимать как固定参数, указывая на то, что вы хотите二维Нарисуйте окружающую среду. Хотя все так думают2dЕстественно должно быть3d, а на самом деле это тоже учтено в самой конструкции, но все не могут немного подождать, поэтому все выбираютwebGL.webGLЧто это такое? Сторона браузера использует системную видеокарту для трехмерного рисования. Это другая история(IEЗабудь это).

  • оcanvas.getContext('2d')Возвращаемое значение

вернутьCanvasRenderingContext2DОбъекты, то есть, как было сказано выше, могут поддерживать большинство операций на холсте.

  1. существуетcanvasрисовать на картинке
   // ctx.drawImage(file,sx,sy,swidth,sheight,x,y,width,height);
ctx.drawImage(this, 0, 0, swidth, sheight);

В случае, когда отсечение не требуется, используйте вышеуказанные параметры для перехвата операцииfileиз всех, предназначенных дляcanvasначальство

О параметрах (w3school)

параметр описывать
file Указывает изображение, холст или видео для использования.
sx Необязательный. Координата x, с которой начинается отсечение.
sy Необязательный. Координата Y для начала отсечения.
swidth Необязательный. Ширина обрезанного изображения.
sheight Необязательный. Высота обрезанного изображения.
x Позиция по координате x для размещения изображения на холсте.
y Координата Y, в которой нужно разместить изображение на холсте.
width Необязательный. Ширина используемого изображения. (растянуть или уменьшить изображение)
height Необязательный. Высота используемого изображения. (растянуть или уменьшить изображение)
  1. Будуcanvasэкспортировать как изображениеsrc
var src = canvas.toDataURL('image/jpeg');

оtoDataURL()метод. Будуcanvasэкспорт контента

canvas.toDataURL(type, encoderOptions);

type: Формат изображения, по умолчаниюimage/jpeg,encoderOptions: Качество изображения, диапазон значений от 0 до 1, значение по умолчанию — 0,92.返回值:Включатьdata URIизDOMString, то есть,base64Формат.

3. Захватите первый кадр видео

Загрузить файл OK, использоватьcanvasПерехват ОК, как найти第一帧Шерстяная ткань? (Когда начнется перехват?)

Конечно, это вызвано мультимедийными событиями. оvideoочень много событий(Все события), здесь обсуждаются только события, которые могут повлиять на первый захваченный кадр.

    video.addEventListener('loadeddata', consoleString.bind(video, 'loadeddata')) // 当前帧加载完毕
	video.addEventListener('loadedmetadata', consoleString.bind(video, 'loadedmetadata')) // 视频元数据加载完毕
	video.addEventListener('canplay', consoleString.bind(video, 'canplay')) // 视频缓冲能够开始播放
	video.addEventListener('timeupdate', consoleString.bind(video, 'timeupdate')) // 播放位置发生改变时
	video.addEventListener('play', consoleString.bind(video, 'play')) // 开始播放时
	video.addEventListener('waiting', consoleString.bind(video, 'waiting')) // 要播放下一帧而需要缓冲时

	function consoleString(string) {
		console.log(string)
	}
// 执行结果
// timeupdate 
// loadedmetadata 
// loadeddata 
// canplay 
// play(开始播放)
// 没有waiting, 因为视频较小不需要缓冲
  • Согласно приказу, первыми на срабатывание оказалисьtimeupdateСобытие, согласно предположению, должно быть выполнено первымloadedmetadata, метаданные загружены. В MDN нет явного заявления об этом, но это можно обосновать:

когдаcurrentTimeСрабатывает при обновленииtimeupdateмероприятие

источник:MDN

loadedmetadataМетаданные ссылаются на时长、尺寸(仅视频)以及文本轨道, то есть вvideoкогда не определеноcurrentTimeдаNaNилиNULL, когда продолжительность в метаданных загружена,currentTimeОбновить до0, тем самым срабатывая.

Вывод: Хотя он и срабатывает первым, видеофайл в это время еще не загружен, и перехватcanvasбез самого содержания.Примечание:timeupdateВ зависимости от используемой системы событие срабатывает от 4 до 66 раз в секунду, а из-за высокой частоты срабатывания единица измерения слишком мала (уровень миллисекунды), и реакцию на событие нужно задерживать, его нельзя полностью контролировать и точно.

  • загруженные метаданные Как упоминалось выше, он запускается после загрузки метаданных, но данные не включают в себя сам видеофайл. Вывод: Если видеофайл большой и время загрузки долгое, все равно невозможно захватить первый загруженный кадр. Дополнение: пропускURL.createObjectURL()Метод может быть практически незаметным, но он небезопасен.

  • загруженные данные Текущий номер кадра (первый кадр) загружается и запускается без проблем. Вывод: имеется. Дополнение: Что делать, если первый кадр черный экран и хотите использовать следующий кадр, извините, количество оставшихся кадров плюс загрузка не входит в его рамки рассмотрения, и это событие не имеет значения.

  • может играть Срабатывает, когда видео может начать воспроизводиться, то есть количество кадров для загрузки (24/25/30/60 и т. д.) определяется в зависимости от количества загруженных видеокадров после того, как экран воспроизведения будет удовлетворен. Резюме: поскольку загрузка относится кloadeddataДля большего количества событий (немного больше) это вообще осуществимо. Добавлено: по контролюcurrentTimeЕго можно удовлетворить (но не так точно, как второй кадр), и его можно рассматривать как «текущий воспроизводимый кадр».

  • играть Он будет срабатывать только при запуске воспроизведения, что не очень соответствует требованию загрузки быстрого перехвата.

  • ожидающий Срабатывает, когда он был воспроизведен, но следующий экран не буферизован должным образом, что подходит для вставки небольшой рекламы.

Файлы, методы, события - все в порядке. Разрез закончился.

    video.addEventListener('loadeddata', function (e) {
		canvas.width = this.videoWidth
		canvas.height = this.videoHeight
		width = this.videoWidth
		height = this.videoHeight
		ctx.drawImage(this, 0, 0, width, height);
		var src = canvas.toDataURL('image/jpeg');
		img.src = src;

		// var currentTime = this.currentTime
		// duration = this.duration
		// var fps = duration / 30
		
	})

Эффект