Dengan mengunggah gambar dengan ukuran yang sesuai, pengguna dapat melihat pratinjau efek yang mirip dengan tayangan slide dengan memilih efek dan musik dari animasi rendering, dan terakhir mengklik untuk mengonfirmasi untuk menghasilkan video, yang dapat diputar di headline atau Douyin.
Solusi yang mungkin untuk menghasilkan videoKonversi pengkodean video front-end murni (seperti WebM Encoder Whammy)
Teruskan setiap frame gambar ke backend untuk implementasi, dan backend memanggil FFmpeg untuk transcoding video.
Pembuatan gambar dapat dicapai melalui antarmuka asli kanvas toDataURL, dan pada akhirnya mengembalikan data gambar dalam bentuk base64.
function generatePng() { var canvas = document.createElement('canvas'); let icavas = '#canvas' //Id kanvas untuk merender animasi if (wrapWidth == 2) { icavas = '#verticalCanvas' } var canvasNode = dokumen .querySelector(icavas) kanvas.lebar = kanvasNode.lebar; kanvas.tinggi = kanvasNode.tinggi var ctx = kanvas.getContext('2d'); ctx.drawImage(canvasNode, 0, 0); var imgData = kanvas.toDataURL(gambar/png); Cara mengambil screenshot animasi kanvasGunakan setInterval untuk menjalankan metode pembuatan gambar secara teratur. Tentu saja, Anda juga dapat menggunakan requestAnimationFrame.
setInterval(fungsi() { imgsTemp.push(generatePng())}, 1000/60) Cara mendapatkan setiap frame gambar di backendSolusi 1: Browser tanpa kepala menjalankan js animasi kanvas front-end, lalu mengambil tangkapan layar js
Ide awal:
Screenshot dicetak menggunakan console.log. Screenshot kanvas dalam format base64, animasi berdurasi 15 detik, dan terdapat lebih dari 100 screenshot, yang secara langsung menyebabkan server crash (ditolak);
Rencana uji coba:
Tangkapan layar disimpan dalam variabel js. Setelah animasi diputar, logo ditambahkan ke halaman, dan kemudian backend mendapatkan variabel tersebut.
halaman const = { imageZoomOut: impor ('./image_zoom_inout.js'), //Zoom imageArt: impor ('./image_art.js'), //Hapus imageGrid: impor ('./image_grid.js'), / /Grid imageRotate: import ('./image_rotate.js'), //Buka dan tutup imageFlash: import ('./image_flash.js'), //Gambar dan teks flash imageVerticalArt: import ('./image_vertical_art.js'), //Penghapusan vertikal imageVerticalGrid: import ('./image_vertical_grid.js'), //Gambar grid vertikalVerticalRotate: import ('. /image_vertical_rotate.js '), //Pembukaan dan penutupan vertikal imageVerticalFlash: import ('./image_vertical_flash.js'), //Gambar vertikal dan flash teks imageVerticalZoomOut: import ('./image_vertical_zoom_inout.js'), //Zoom vertikal imageVertical: import ('./image_vertical.js'), //Versi vertikal umum};var isShow = falsevar imgsBase64 = []var imgsTemp = []var cutInter = nullvar imgsTimeLong = 0fungsi getQuerys(tag) { biarkan queryStr = window.location.search.slice(1); biarkan queryArr = queryStr.split('&'); biarkan query = []; biarkan spesifikasi = {} untuk (biarkan i = 0, len = queryArr.length; i < len ; i++) { biarkan queryItem = queryArr[i].split('='); biarkan qitem = decodeURIComponent(queryItem[1]) if (queryItem[0] == tag) { query.push(qitem); } else { spesifikasi[queryItem[0]] = qitem } } kembali { daftar: kueri, spesifikasi: spesifikasi };}var getQuery = getQuerys('images')var effectTag = getQuery.spec. tidvar wrapWidth = getQuery.spec.templateTypelet num = 0biarkan imgArr = []fungsi creatImg() { var gambar = getQuery.list biarkan newImg = [] biarkan vh = wrapWidth == 1 ? 360 : 640 biarkan vw = wrapWidth == 1 ? (item, indeks) { if (11 === indeks || 13 === indeks || 16 === indeks) { var temp = Gambar baru(vw, vh) temp.setAttribute('crossOrigin', 'anonim'); temp.src = item; newImg.push(temp) } else { newImg.push(item) } }) imgArr = newImg renderAnimate( effectTag) } else { gambar.peta(fungsi(item) { var temp = Gambar baru(vw, vh) temp.setAttribute('crossOrigin', 'anonim'); temp.src = item; temp.onload = function() { num++ if (num == gambar.panjang) { renderAnimate(effectTag) } } newImg.push(temp) }) imgArr = newImg }}async function renderAnimate(halaman) { //tunggu creatImg() izinkan saya = const pageA = ini tunggu halaman[halaman]; biarkan oldDate = Tanggal baru().getTime() biarkan icavas = '#canvas' if (wrapWidth == 2) { icavas = '#verticalCanvas' } biarkan innerCanvas = document.querySelector(icavas) isShow = false pageA[page].render(null, { canvas: innerCanvas, images: imgArr }, function() { //Setelah animasi diputar isShow = benar; imgsTemp.push(generatePng()) imgsBase64.push(imgsTemp) biarkan sekarang = new Date().getTime() window.imgsTimeLong = sekarang - oldDate clearInterval(cutInter) document.getElementById('cutImg').innerHTML = ' selesai'//Identifikasi halaman}) cutInter = setInterval(function() { imgsTemp.push(generatePng()) if (imgsTemp.length >= 50) { imgsBase64.push(imgsTemp) imgsTemp = [] } }, 130)}fungsi getImgs() { return imgsBase64}fungsi generatePng() { var canvas = document.createElement('kanvas'); biarkan icavas = '#kanvas' jika (wrapWidth == 2) { icavas = '#verticalCanvas' } var canvasNode = document.querySelector(icavas) canvas.width = canvasNode.width canvas.height = canvasNode.height; ; ctx.drawImage(canvasNode, 0, 0); canvas.toDataURL(image/png); return imgData;}window.imgsBase64 = imgsBase64 //Variabel penyimpanan tangkapan layar creatImg()Kerugian dari rencana operasi percobaan:
var temp = Gambar baru(vw, vh)temp.setAttribute('crossOrigin', 'anonymous'); Solusi terakhir: jalankan animasi di sisi NODE Gunakan node-canvas untuk menulis setiap tangkapan layar bingkai ke folder tertentu menggunakan fs.writeFile
const { createCanvas, loadImage} = memerlukan(kanvas); halaman const = { imageZoomOut: memerlukan('./image_zoom_inout.js'), //Zoom imageArt: memerlukan('./image_art.js'), //Hapus imageGrid : memerlukan('./image_grid.js'), //Grid imageRotate: memerlukan('./image_rotate.js'), //Membuka dan menutup imageFlash: require('./image_flash.js'), //Gambar dan teks flash imageVerticalArt: require('./image_vertical_art.js'), //Penghapusan vertikal imageVerticalGrid: require('./image_vertical_grid . js'), //gambar kisi vertikalVerticalRotate: memerlukan('./image_vertical_rotate.js'), //gambar kisi vertikalVerticalFlash: require('./image_vertical_flash.js'), //gambar vertikal dan teks flash imageVerticalZoomOut: require('./image_vertical_zoom_inout.js'), //zoom vertikal imageVertical: require('./image_vertical.js'), // Umum untuk versi vertikal};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 //tinggi kanvas let vw = parse.templateType == 1 ? let imgSrcArray = parse.images //Array gambar let effectTag = parse.tid //Efek animasi let saveImgPath = proses.argv && proses.argv[3]biarkan loadArr = []imgSrcArray.forEach(element => { if (//.(jpg|jpeg|png|JPG|PNG)$/.test(element)) { loadArr.push(loadImage(elemen)) } else { loadArr.push(elemen) }});const kanvas = createCanvas(vw, vh);const ctx = canvas.getContext(2d);Promise.all(loadArr) .then((images) => { //Inisialisasi animasi console.log('Mulai animasi') biarkan oldDate = new Date ().getTime() halaman[effectTag].render(null, { kanvas: kanvas, gambar: gambar }, function() { clearInterval(interval) biarkan sekarang = baru Date().getTime() console.log(sekarang - oldDate, 'Animasi berakhir') }) const interval = setInterval( (function() { let x = 0; return () => { x += 1; ctx. canvas.toDataURL('image/jpeg', function(err, png) { if (err) { console.log(err); return; } biarkan data = png.replace(/^data:image///w+;base64,/, ''); biarkan buf = new Buffer(data, 'base64'); fs.writeFile(`${saveImgPath}${x}.jpg `, buf, {}, (err) => { konsol.log(x, err); 1000/60 ); }) .catch(e => { konsol.log(e); });Jalankan perintah berikut di bawah iterm
simpul 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 =../pantat ets/imgs/8.png&images=../assets/imgs/7.png&images=../assets/imgs/4.png&images=../assets/imgs/6.png&images=../assets/imgs/8. png&gambar=../aset/imgs/7.png' './gambar/'
Deskripsi parameter:
1) tid adalah nama animasinya
2) tipe template berukuran: 1:1280*720;
3) gambar adalah alamat gambar
4) Variabel './images/' adalah alamat penyimpanan tangkapan layar,
Kerugian berjalan di lingkungan NODEUlangi gambar berikut setiap 13 detik:
untuk (var A = 0; 50 > A; A++) p.beginPath(), p.globalAlpha = 1 - A / 49, p.save(), p.arc(180,320,P + 2 * A, 0, 2 * Matematika.PI), p.clip(), p.drawImage(x[c], 0, 0, y.width, y.height), p.restore(), p.closePath(); untuk (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.lebar, y.tinggi), p.restore(), p.closePath();
Karena model event loop Node.js, penggunaan Node.js harus memastikan bahwa siklus Node.js dapat berjalan setiap saat. Jika muncul fungsi yang sangat memakan waktu, event loop akan macet dan tidak dapat ditangani tugas-tugas lain pada waktunya, jadi Akibatnya, beberapa animasi masih lambat
Kemungkinan optimasi nantiCoba gunakan bahasa Go untuk mengambil tangkapan layar;
Menulis ulang animasi kanvas;
tambahan Kecepatan bit videoBit rate video adalah jumlah bit data yang dikirimkan per satuan waktu selama transmisi data. Umumnya satuan yang kita gunakan adalah kbps, yaitu ribuan bit per detik. Pengertian sederhananya adalah sampling rate. Semakin besar sampling rate per satuan waktu, semakin tinggi akurasinya, dan semakin dekat file yang diproses dengan file aslinya. Misalnya, untuk suatu audio, semakin tinggi bit rate-nya, semakin kecil rasio kompresinya, semakin kecil pula kehilangan kualitas suara, dan semakin dekat kualitas suara tersebut dengan sumber audio.
Bingkai FPS per detik (Bingkai Per Detik))
FPS adalah definisi di bidang grafis, yang mengacu pada jumlah frame yang ditransmisikan per detik. Secara umum, ini mengacu pada jumlah frame animasi atau video. FPS adalah ukuran jumlah informasi yang digunakan untuk menyimpan dan menampilkan video dinamis. Semakin banyak frame per detik, semakin halus aksi yang ditampilkan. Umumnya minimal untuk menghindari gerakan tersentak-sentak adalah 30. Misalnya, sebuah film diputar dengan kecepatan 24 frame per detik, yang berarti 24 frame diam diproyeksikan secara terus menerus ke layar dalam satu detik.
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.