FFCreator
FFCreator copied to clipboard
通过Lite版本,组合视频+图片,无法得到音频
FFMPEG版本 4.4.1,Ubuntu 20.04,Node 14
我们用了Lite版本官方demo里面的video.js做参考,将视频和图片进行组合的时候。
sence1 = 原视频,有声音 sence2 = 原图片转的视频
视频合成是没有问题的。但cache中的sence1.mp4将原视频中的音频丢失掉了。
我们试图用API,FFVideo中提供的audio部分设置为true,但组合视频的时候,却又碰到这样的错误提示: TypeError: fvideo1.setAudio is not a function
然后我们就不知道怎么办了。随后我们把官方demo中的lite版本,下载到本地,在上述环境中运行,官方demo中的video.js生成出来的demo,同样没有音频。。。
请问这大概是什么原因造成的呢?是我们有什么库没有安装?还是Node或其他依赖库的版本问题?
---- 附注我们运行时的log
第一部分,视频准备: single: ffmpeg -loop 1 -i /webapp/agencyfolio/node_modules/ffcreatorlite/lib/assets/blank.png -i https://accelerate.1f.sale/publicProperty/video/HCPP1-Tm7A9OEvQr/6bcc58606e7e81b898c2ebc925cd5fba0b495421.mp4 -y -filter_complex color=c=#000000:d=30:size=600600[background1-0];[background1-0][0:v]overlay=x=-10:y=0[image1-1];[1:v]scale=iw0.47:ih*0.47[video1-1];[image1-1][video1-1]overlay=x=0:y=161.25[video1-2] -map [video1-2] -r 24 -t 30 -hide_banner -map_metadata -1 -map_chapters -1 -c:v libx264 -profile:v main -preset medium -crf 20 -movflags faststart -pix_fmt yuv420p -map 0 /webapp/agencyfolio/cache/r0rctr851qwppj2r/scene1.mp4
↑ 这个sence1.mp4,就是丢失了音频的原视频
single: ffmpeg -loop 1 -i /webapp/agencyfolio/node_modules/ffcreatorlite/lib/assets/blank.png -loop 1 -i /webapp/agencyfolio/public/video//fooHCUR-cMIyMJH68B.png -y -filter_complex color=c=#ffffff:d=999999:size=600*600[background3-0];[background3-0][0:v]overlay=x=-10:y=0[image2-1];[image2-1][1:v]overlay=x=0:y=0[image3-1] -map [image3-1] -r 24 -t 10 -hide_banner -map_metadata -1 -map_chapters -1 -c:v libx264 -profile:v main -preset medium -crf 20 -movflags faststart -pix_fmt yuv420p -map 0 /webapp/agencyfolio/cache/8o58riilrtamrcze/scene2.mp4
第二部分,视频合成 ffmpeg -i /webapp/agencyfolio/cache/pz679lk9c3gbyi2t/scene1.mp4 -i /webapp/agencyfolio/cache/5tvrgk046tfq8gj2/scene2.mp4 -y -filter_complex [0:v][1:v]xfade=transition=hlslice:duration=1.5:offset=28.5[scene-0] -map [scene-0] -hide_banner -map_metadata -1 -map_chapters -1 -c copy -c:v libx264 -profile:v main -preset medium -crf 20 -movflags faststart -pix_fmt yuv420p -r 24 /webapp/agencyfolio/public/video/videoHCPP1-Tm7A9OEvQr_HCUR-cMIyMJH68B.mp4
setAudio is the api of ffcreator, not the api of the lite version. Are you using the standard version of ffmpeg?
Maybe you can upload the project
- we have tried setAudio on both FF and lite version, it reported the same error message
- we also tried using lite version official demo code (video.js), but running on our environment, result is also disappointing.
- FFMPEG was a direct apt-get from repository. and we are at FFMPEG 4.4.1
Here is our video.js code clip - USING FFcreator
import apis, { apilawyerAdd } from '../../../utils/apis' import utils from '../../../utils/utils' const path = require('path'); import colors from 'colors' import { FFCreatorCenter, FFScene, FFImage, FFCreator, FFVideo,FFAudio } from 'ffcreator' import pdf from 'html-pdf'; import { pageTPL } from '../../../theme/default/video/video' import withSession from '../../../utils/session' import getVideoWH from 'get-video-width-height' import store from "store"; import expirePlugin from 'store/plugins/expire' const getVideoDuration = require('node-video-duration'); export default withSession(async (req, res) => { const { hash, unit_hash, update_time, color, videourl } = req.query
const tphash = req.session.get('tphash'); const type = req.query.type && req.query.type != undefined ? parseInt(req.query.type) : 0 const isEn = req.query.isEn && req.query.isEn != undefined ? parseInt(req.query.isEn) : 0 //0中文 1英文 2繁体 const debug = req.query.debug && req.query.debug != undefined ? parseInt(req.query.debug) : 0; const quality = req.query.quality && req.query.quality != undefined ? parseInt(req.query.quality) : 0; const ROOT_PATH = process.cwd(); var fs = require('fs');
// const video1 = videourl && videourl != undefined ? videourl : path.join(ROOT_PATH, '/assets/video/video3.mp4'); const outputDir = path.join(ROOT_PATH, '/public/video/'); const cacheDir = path.join(ROOT_PATH, '/cache/');
if (tphash && tphash != undefined) { let tpname = utils.setthirdparty(apis, tphash) if (tpname) {
const token = await utils.token(fs, apis, tpname);
let authToken = await utils.authToken(apis, req, token);
const body = await Promise.all([
apiV2flowDetail_store(token, hash),
utils.userinfo(apis, token, authToken)
//apitphashpartysystemBottom(token)
])
const [_details, _userinfo] = body
if (_details.code == 0) {
var details = _details.data
var video1 = details.video
if (details.video) {
// const _userinfo = await utils.userinfo(apis, token, authToken)
let usercard = {}
if (_userinfo.code == 0) {
let myinfo = _userinfo.data
const userinfo = req.session.get('userinfo');
usercard = userinfo;
usercard.role_type = myinfo.portal_info.role_type
usercard.is_company = myinfo.portal_info.is_company
usercard.portal = {}
usercard.portal.hash = myinfo.portal_info.hash
usercard.portal.logo = myinfo.portal_info.primary_image.thumb.replace("/format/webp", "/format/png")
usercard.portal.name = myinfo.portal_info.name_en
usercard.portal.name_cn = myinfo.portal_info.name_cn
usercard.name = userinfo.first_name ? userinfo.first_name : '';
usercard.surname = userinfo.last_name ? userinfo.last_name : ''
usercard.qrcode = myinfo.qrcode.replace("/format/webp", "/format/jpg")
usercard.avatar = myinfo.avatar.replace("/format/webp", "/format/jpg");
let imgpath = outputDir + '/foo' + usercard.hash + '.png';
let img=await pdfIMG(fs,utils,req,imgpath,usercard);
var number = details.hash+"_"+usercard.hash;
let filename = "video" + number;
let filetype="mp4";
let filepath=filename+"."+filetype
let videopath=outputDir + filepath
console.log("videopath",videopath);
console.log("videourl",video1);
let video= await videoEdit(fs,cacheDir,outputDir,img,videopath,video1);
res.statusCode = 200
res.json({
code:0,
data:{
filename,
filename,
fileurl:"/video/"+filepath
}
});
}else{
res.statusCode = 200
res.json(_userinfo);
}
} else {
res.statusCode = 200
res.json({
code: 404,
message_cn: "找不到视频文件!",
message_en: "Video file not found!"
})
}
} else {
res.statusCode = 200
res.json(_details);
}
} else {
res.statusCode = 200
res.json({
code: 417,
message: "第三方信息不对!"
})
}
} else { res.statusCode = 200 res.json({ code: 417, message_cn: "登录过期,重新登录", message_en: "Your login credential has expired, please login agian." })
}
}) function apiV2flowDetail_store(token, hash) { return new Promise(async (resolve, reject) => { let details = store.get("detailsFlow_" + hash); //console.log("details_time",JSON.parse(details_time),JSON.parse(details).data.update_time,JSON.parse(details_time)==JSON.parse(details).data.update_time?1:2) if (details && details != undefined) { resolve(details) } else { const body = await apiV2flowDetail(token, hash); resolve(body) if (body.code == 0) { store.set("detailsFlow_" + hash, body) } }
}) } function apiV2flowDetail(token, hash) { var url = apis.apiBaseUrl + apis.apiV2flowDetail return utils._get(url, { token: token, scene: "pwa", hash: hash }) } function pdfIMG(fs,utils,req,imgpath,usercard){ return new Promise(async (resolve, reject) => { fs.exists(imgpath, (exists) => { if (exists) { console.log("图片文件已存在"); resolve(imgpath) } else { console.log("图片文件不存在"); let host = req.headers.host // let TPhost = utils.setTPhost(host, tpname, parseInt(isEn) ? "en" : "zh", "zh") // usercard.avatar=""; let H5url = "https://"+host var tpl = pageTPL(utils, usercard, H5url); const ROOT_PATH = process.cwd(); var Html = fs.readFileSync(ROOT_PATH + '/theme/default/video/video.html', 'utf8'); // console.log("tpl",tpl); var htmldata = Html.replace("{{page}}", tpl); var options = { height: 600 + "px", width: 600 + "px", phantomArgs: ['--ignore-ssl-errors=yes'], "localUrlAccess": true, type: "png", "quality": "100", };//"localUrlAccess": false, pdf.create(htmldata, options).toStream(async function (err, stream) {
stream.pipe(fs.createWriteStream(imgpath));
console.log("生成图片成功!");
resolve(imgpath)
})
}
});
}) } async function videoEdit(fs,cacheDir,outputDir,img,videopath,videourl){ return new Promise(async (resolve, reject) => { fs.exists(videopath,async (exists) => { if (exists) { console.log("视频文件已存在"); resolve(videopath) } else { console.log("视频生成中"); const width = 600; const height = 600; // create creator instance const creator = new FFCreator({ cacheDir, outputDir, width: width, height: height, audioLoop: true, debug:true });
creator.setOutput(videopath);
//create FFScene
const scene1 = new FFScene();
// scene1.setBgColor('#9980fa');
const scene2 = new FFScene();
scene2.setBgColor('#ffffff');
let video_info = await getVideoWH(videourl);
console.log("video_info", video_info);
let video_w = 0, video_h = 0;
let pot = video_info.width / video_info.height
console.log("aaa", Math.ceil(pot));
let Scale = 1, x = 0, y = 0;
if (Math.ceil(pot) > 1) {
video_w = width;
video_h = (width * video_info.height) / video_info.width
Scale = width / video_info.width
Scale = Scale.toFixed(2)
y = (height - video_h) / 2
} else {
video_w = (width * video_info.width) / video_info.height;
video_h = width
Scale = width / video_info.height
}
console.log(video_w, video_h)
const Duration= await getVideoDuration(videourl);
console.log("Duration",Duration);
const fvideo1 = new FFVideo({ path: videourl, y: y });
fvideo1.setScale(Scale);
// fvideo1.setAudio(true);
scene1.addChild(fvideo1);
scene1.setDuration(Duration);
scene1.setTransition('hlslice', 1.5);
creator.addChild(scene1);
const fimg = new FFImage({ path: img, x: 0, y: 0 });
fimg.setScale(1);
// flogo.addEffect('fadeIn', 2.5, 1.5);
scene2.addChild(fimg);
creator.addChild(scene2);
creator.start();
creator.openLog();
creator.on('start', () => {
console.log(`FFCreatorLite start`);
});
creator.on('error', e => {
console.log(`FFCreatorLite error:: \n ${e.error}`);
});
creator.on('progress', e => {
console.log(colors.yellow(`FFCreatorLite progress: ${(e.percent * 100) >> 0}%`));
});
creator.on('complete', e => {
console.log(
colors.magenta(`FFCreatorLite completed: \n USEAGE: ${e.useage} \n PATH: ${e.output} `),
);
console.log(colors.green(`\n --- You can press the s key or the w key to restart! --- \n`));
const file = e.output;
console.log("e11111", e)
// res.setHeader('Content-Type', 'video/mp4; charset=utf-8');
resolve(file)
});
}
});
}) }
手动看看两个视频文件的编码 视频和音频 是不是一致的 输出的视频 codec和acodec编码是不是一致