Загрузив изображение соответствующего размера, пользователи могут просмотреть эффект, аналогичный слайд-шоу, выбрав эффект и музыку анимации рендеринга и, наконец, щелкнув для подтверждения, чтобы создать видео, которое можно воспроизвести в заголовках или Douyin.
Возможные решения для создания видеоЧистое внешнее преобразование кодирования видео (например, WebM Encoder Whammy)
Передавайте каждый кадр изображения на серверную часть для реализации, а серверная часть вызывает FFmpeg для перекодирования видео.
Генерация изображения может быть достигнута через собственный интерфейс Canvas toDataURL и в конечном итоге возвращает данные изображения в форме Base64.
functiongeneratePng() { var Canvas = document.createElement('canvas'); let icavas = '#canvas' //Идентификатор холста для рендеринга анимации if (wrapWidth == 2) { icavas = '#verticalCanvas' } var CanvasNode = document .querySelector(icavas) Canvas.width = CanvasNode.width; Canvas.height = CanvasNode.height; Canvas.getContext('2d'); ctx.drawImage(canvasNode, 0, 0); var imgData = Canvas.toDataURL(image/png); return imgData;}Как сделать скриншоты анимации холста
Используйте setInterval для регулярного выполнения метода генерации изображений. Конечно, вы также можете использовать requestAnimationFrame.
setInterval(function() { imgsTemp.push(generatePng())}, 1000/60)Как получить каждый кадр изображения в серверной части
Решение 1. Безголовый браузер запускает интерфейсную анимацию холста js, а затем делает снимок экрана js.
Первоначальная идея:
Скриншоты распечатываются с помощью console.log. Скриншоты холста имеют формат base64, 15-секундную анимацию, и имеется более 100 скриншотов, которые непосредственно привели к сбою сервера (отклонено);
План пробного запуска:
Скриншот сохраняется в переменной js. После воспроизведения анимации на страницу добавляется логотип, а затем серверная часть получает переменную. Код выглядит следующим образом:
const страницы = { imageZoomOut: import ('./image_zoom_inout.js'), // Масштабирование imageArt: import ('./image_art.js'), // Стереть imageGrid: import ('./image_grid.js'), / /Grid imageRotate: import ('./image_rotate.js'), //Открытие и закрытие imageFlash: import ('./image_flash.js'), //Изображение и текст flash imageVerticalArt: import ('./image_vertical_art.js'), //Стирание по вертикали imageVerticalGrid: import ('./image_vertical_grid.js'), //Вертикальная сетка imageVerticalRotate: import ('. /image_vertical_rotate.js '), //Вертикальное открытие и закрытие imageVerticalFlash: import ('./image_vertical_flash.js'), //Вертикальное изображение и текст flash imageVerticalZoomOut: import ('./image_vertical_zoom_inout.js'), //Вертикальное масштабирование imageVertical: import ('./image_vertical.js'), //Общая вертикальная версия};var isShow = falsevar imgsBase64 = []var imgsTemp = []var CutInter = nullvar imgsTimeLong = 0function getQuerys(tag) { let queryStr = window.location.search.slice(1); let queryArr = queryStr.split('&'); let query = []; let spec = {} for (let i = 0, len = queryArr.length; i < len ; i++) { let queryItem = queryArr[i].split('='); let qitem = decodeURIComponent(queryItem[1]) if (queryItem[0] == тег) { query.push(qitem); } else { spec[queryItem[0]] = qitem } } return { list: query, spec: spec };}var getQuery = getQuerys('images')var effectTag = getQuery.spec. tidvar WrapWidth = getQuery.spec.templateTypelet num = 0let imgArr = []function creatImg() { var images = getQuery.list let newImg = [] let vh = WrapWidth == 1 ? 360 : 640 let vw = WrapWidth == 1 ? 640 : 360 if (effectTag.indexOf('Flash') > -1) { images.map(function (элемент, индекс) { if (11 === индекс || 13 === индекс || 16 === индекс) { var temp = новое изображение(vw, vh) temp.setAttribute('crossOrigin', 'anonymous'); temp.src = item; newImg.push(temp) } else { newImg.push(item) } }) imgArr = newImg renderAnimate( effectTag) } else { images.map(function(item) { var temp = new Image(vw, vh) temp.setAttribute('crossOrigin', 'anonymous'); temp.src = item; temp.onload = function() { num++ if (num == images.length) { renderAnimate(effectTag) } } newImg.push(temp) }) imgArr = newImg }}async function renderAnimate(page) { //ждём creatImg() let me = this const pageA = awaitpages[page]; let oldDate = new Date().getTime() let icavas = '#canvas' if (wrapWidth == 2) { icavas = '#verticalCanvas' } let InternalCanvas = document.querySelector(icavas) isShow = false pageA[page].render(null, { Canvas: InternalCanvas, images: imgArr }, function() { //После воспроизведения анимации isShow = true imgsTemp.push(generatePng()) imgsBase64.push(imgsTemp) let now = new Date().getTime() window.imgsTimeLong = now - oldDateclearInterval(cutInter) document.getElementById('cutImg').innerHTML = '; Done'//Идентификация страницы}) CutInter = setInterval(function() { imgsTemp.push(generatePng()) if (imgsTemp.length >= 50) { imgsBase64.push(imgsTemp) imgsTemp = [] } }, 130)}function getImgs() { return imgsBase64}functiongeneratePng() { var Canvas = document.createElement('canvas'); let icavas = '#canvas' if (wrapWidth == 2) { icavas = '#verticalCanvas' } var CanvasNode = document.querySelector(icavas) Canvas.width = CanvasNode.width; Canvas.height = CanvasNode.height; var ctx = Canvas.getContext('2d') ctx.drawImage(canvasNode, 0, 0); вар imgData =; Canvas.toDataURL(image/png); return imgData;}window.imgsBase64 = imgsBase64 //Переменная для хранения снимков экрана creatImg()
Недостатки плана опытной эксплуатации:
var temp = new Image(vw, vh)temp.setAttribute('crossOrigin', 'anonymous');Окончательное решение: запустить анимацию на стороне NODE.
Используйте node-canvas для записи каждого скриншота кадра в указанную папку с помощью fs.writeFile
const { createCanvas, loadImage} = require(canvas); constpages = { imageZoomOut: require('./image_zoom_inout.js'), //Увеличение изображенияImageArt: require('./image_art.js'), //Стереть imageGrid: require('./image_grid.js'), //Сетка imageRotate: require('./image_rotate.js'), //Открытие и закрытие imageFlash: require('./image_flash.js'), //Флэш-изображение и текст imageVerticalArt: require('./image_vertical_art.js'), //Стирание по вертикали imageVerticalGrid: require('./image_vertical_grid . js'), //вертикальная сетка imageVerticalRotate: require('./image_vertical_rotate.js'), //вертикальная сетка imageVerticalFlash: require('./image_vertical_flash.js'), //Вертикальное изображение и текст в flash imageVerticalZoomOut: require('./image_vertical_zoom_inout.js'), //Вертикальное масштабирование imageVertical: require('./image_vertical.js'), // Общее для вертикальной версии};const fs = require(fs);const querystring = require('querystring');let args =process.argv &&process.argv[2]let parse = querystring.parse(args)let vh = parse.templateType == 1 ? 720: 1280 // высота холста let vw = parse.templateType == 1 ? let imgSrcArray = parse.images // Массив изображений let effectTag = parse.tid // Эффект анимации let saveImgPath =process.argv &&process.argv[3]let loadArr = []imgSrcArray.forEach(element => { if (//.(jpg|jpeg|png|JPG|PNG)$/.test(element)) { loadArr.push(loadImage(element)) } else { loadArr.push(element) }});const Canvas = createCanvas(vw, vh);const ctx = Canvas.getContext(2d);Promise.all(loadArr) .then((images) => { //Инициализируем анимацию console.log('Начать анимацию') let oldDate = новая дата ().getTime()pages[effectTag].render(null, {canvas: Canvas, images: images}, function() {clearInterval(interval) let now = new Date().getTime() console.log(сейчас — oldDate, «Анимация заканчивается») }) const интервал = setInterval( (function() { let x = 0; return () => { x += 1; ctx. Canvas.toDataURL('image/jpeg', function(err, png) { if (err) { console.log(err); return; } let data = png.replace(/^data:image///w+;base64,/, ''); let buf = new Buffer(data, 'base64'); `, buf, {}, (ошибка) => { console.log(x, err); return }); 1000/60 }) .catch(e => { console.log(e); });
Выполните следующую команду под iterm
узел testCanvas.js 'tid=imageArt&templateType=1&images=../assets/imgs/8.png&images=../assets/imgs/6.png&images=../assets/imgs/7.png&images=../assets/imgs/6.png&images =../жопа ets/imgs/8.png&images=../assets/imgs/7.png&images=../assets/imgs/4.png&images=../assets/imgs/6.png&images=../assets/imgs/8. png&images=../assets/imgs/7.png' './изображения/'
Описание параметра:
1) tid — название анимации
2) templateType — размер: 1:1280*720 2:720*1280;
3) images — адрес изображения
4) Переменная './images/' — это адрес, по которому сохраняется скриншот,
Недостатки работы в среде NODEСледующий рисунок повторяется каждые 13 секунд:
for (var A = 0; 50 > A; A++) p.beginPath(), p.globalAlpha = 1 - A/49, p.save(), p.arc(180,320,P + 2 * A, 0, 2 * Math.PI), p.clip(), p.drawImage(x[c], 0, 0, y.width, y.height), p.restore(), p.closePath(); for (var S = 0; 50 > S; S++) p.beginPath(), p.globalAlpha = 1 - S/49, p.save( ), p.rect(0, 0, d + P + 2 * S, g + b + 2 * S), p.clip(), p.drawImage(x[c], 0, 0, y.ширина, y.высота), p.restore(), p.closePath();
Из-за модели цикла событий Node.js использование Node.js должно гарантировать, что цикл Node.js может выполняться в любое время. Если появляется очень трудоемкая функция, цикл событий зависает и не может быть обработан. другие задачи вовремя, поэтому некоторые анимации по-прежнему работают медленно.
Возможность последующей оптимизацииПопробуйте использовать язык Go для создания снимков экрана;
Переписать анимацию холста;
дополнительный Битрейт видеоСкорость передачи видео — это количество бит данных, передаваемых за единицу времени во время передачи данных. Обычно мы используем единицу измерения — кбит/с, то есть тысячи бит в секунду. Простое понимание — это частота дискретизации. Чем больше частота дискретизации в единицу времени, тем выше точность и тем ближе обработанный файл к исходному файлу. Например, для звука, чем выше скорость передачи данных, тем меньше степень сжатия, тем меньше потеря качества звука и тем ближе качество звука к источнику звука.
FPS кадров в секунду (Frames Per Second)
FPS — это определение в области графики, которое относится к количеству кадров, передаваемых в секунду. Вообще говоря, это относится к количеству кадров анимации или видео. FPS — это мера объема информации, используемой для сохранения и отображения динамического видео. Чем больше кадров в секунду, тем плавнее отображается действие. Обычно минимум, позволяющий избежать резких движений, составляет 30. Например, фильм воспроизводится со скоростью 24 кадра в секунду, а это означает, что за одну секунду на экране непрерывно проецируются 24 неподвижных кадра.
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.