bat编写
做出一个初始模型, 使得视频出现弹幕文字
ffplay -i input.mp4 -vf "drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='test':x=w-100*t:y=50"
将这个放入一个bat文件之中
@echo off
setlocal enabledelayedexpansion
rem 获取文件名,不带扩展名
set "barrage='hello'"
rem 执行 ffmpeg 命令
ffplay -i input.mp4 -vf "drawtext=fontsize=20:fontfile=FreeSerif.ttf:text=!barrage!:x=w-100*t:y=1"
endlocal
在固定时间显示文字并移动
ffplay -i input.mp4 -vf "drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='test':x=w-100*(t-10):y=50:enable=gt(t,10)"
如何添加多个文字
ffplay -i input.mp4 -vf "drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='Text1':x=100:y=50:enable=gt(t\,1)*lt(t\,20),drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='Text2':x=100:y=100:enable=gt(t\,3)*lt(t\,40)"
将多个文字和时间整合在一起
ffplay -i input.mp4 -vf "drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='Text1':x=w-100*(t-1):y=50:enable=gt(t\,1)*lt(t\,20),drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='Text2':x=w-100*(t-3):y=100:enable=gt(t\,3)*lt(t\,40)"
使用bat做二层循环
@echo off
setlocal enabledelayedexpansion
set "TEXT_INFO=Text1 10 20 100 50;Text2 30 40 200 100;Text3 60 70 300 150"
rem 遍历每个分号分隔的部分
for %%A in ("%TEXT_INFO:;=";"%") do (
echo Processing: %%~A
rem 使用空格分隔每个部分
for %%B in (%%~A) do (
echo %%~B
)
)
endlocal
结果显示为
Processing: Text1 10 20 100 50
Text1
10
20
100
50
Processing: Text2 30 40 200 100
Text2
30
40
200
100
Processing: Text3 60 70 300 150
Text3
60
70
300
150
但是如果想要对每一个项对应一个变量操作, 可以使用
@echo off
setlocal enabledelayedexpansion
set "TEXT_INFO=Text1 10 20 100 50;Text2 30 40 200 100;Text3 60 70 300 150"
rem 遍历每个分号分隔的部分
for %%A in ("%TEXT_INFO:;=";"%") do (
echo Processing: %%~A
rem 使用空格分隔每个部分
set count=0
for %%B in (%%~A) do (
set /a count+=1
set "ITEM!count!=%%~B" rem 将每个项赋值给 ITEM1, ITEM2, ...
)
rem 输出所有赋值的项
for /L %%C in (1,1,!count!) do (
echo ITEM%%C: !ITEM%%C!
)
)
endlocal
结果为
Processing: Text1 10 20 100 50
ITEM1: Text1
ITEM2: 10
ITEM3: 20
ITEM4: 100
ITEM5: 50
Processing: Text2 30 40 200 100
ITEM1: Text2
ITEM2: 30
ITEM3: 40
ITEM4: 200
ITEM5: 100
Processing: Text3 60 70 300 150
ITEM1: Text3
ITEM2: 60
ITEM3: 70
ITEM4: 300
ITEM5: 150
通过以上内容,可以得到雏形
@echo off
setlocal enabledelayedexpansion
:: 设置视频文件名
set VIDEO_FILE=hy.mp4
:: 定义文本信息和时间
:: 格式: 文本内容 起始时间 结束时间 X坐标 Y坐标
set "TEXT_INFO=Text1 1 20 10 50;Text2 3 40 20 100;Text3 5 70 50 150"
::x=w-100*(t-10)
:: 初始化 FFmpeg 命令字符串
set FFMPEG_CMD=ffplay -i "%VIDEO_FILE%" -vf "
rem 遍历每个分号分隔的部分
for %%A in ("%TEXT_INFO:;=";"%") do (
echo Processing: %%~A
echo "--------------------"
rem 使用空格分隔每个部分
set count=0
for %%B in (%%~A) do (
set /a count+=1
set "ITEM!count!=%%~B" rem 将每个项赋值给 ITEM1, ITEM2, ...
)
echo ".................."
::!FFMPEG_CMD!
set "FFMPEG_CMD=!FFMPEG_CMD!drawtext=fontsize=20:fontfile=FreeSerif.ttf:text='!ITEM1!':x=w-100*(t-!ITEM2!):y=!ITEM5!:enable=gt(t\,!ITEM2!),"
echo !FFMPEG_CMD!
)
:: 移除最后一个逗号并添加结束方括号
set FFMPEG_CMD=!FFMPEG_CMD:~0,-1!"
echo !FFMPEG_CMD!
endlocal
接下来可以将想要放入的弹幕以及格式填入TEXT_INFO中,但是如果弹幕太多, 会显示The input line is too long,那其实我们可以多试几次
@echo off
setlocal enabledelayedexpansion
set VIDEO_FILE=hy.mp4
set "TEXT_INFO=⭐———————— 27 16777215 300 25;我在叙利亚都没受过这么重的伤 107 16776960 270 25;底部淡蓝色字幕菌施工完毕,感谢欣赏 96 8700107 270 25;“升空的烟火,是圆的,还是扁的?”“圆的也好,扁的也好,奇怪形状也罢。只要我们俩在一起,什么我都不在乎。” 35 16646914 30 25;烟花易逝,人情长存 3 16707842 270 25;樱花易逝,春树常绿,以声之色,塑以花之形,将你之名,刻之我心。 75 16777215 270 25;赶快去表白,别留遗憾!!! 55 16646914 30 25;君(きみ)の後(うし)ろ姿(すがた)你留下背影的那天 15 9033215 300 25;焰色反应() 26 16707842 240 25;此时,西片正在找高木 99 15138834 270 25;底部淡蓝色中文字幕君开始施工,并非翻译 7 8700107 240 25;2022中考顺利!加油!! 35 16707842 270 25;↑说句人话:我爱你西宫硝子↑ 38 16776960 180 25;两年了,我已经放下啦 20 16707842 300 25;烟花易逝,人情长存 13 15138834 0 25;烟花易逝,人情长存 91 16777215 300 25;每当听到这首歌我心里就百感交集 34 16776960 0 25;烟花易逝,人情长存 0 16776960 180 25;此生无悔二次元,来世还做纸片人 116 15138834 60 25;还能坚持下去等一个人吗,已经错过了一整个青春 31 16777215 90 25;宋老师,您一定要幸福,我才不会遗憾 5 8700107 210 25;把灯火都灭掉,拨动寒冷的月光 66 16765698 180 25;打上军火 0 6830715 30 25;有情人终成兄妹(狗头) 110 15138834 270 25;等到有彩虹,你的脸亮起美丽的容光 40 16765698 90 25;这懵懂的感情在内心迸发 31 16765698 210 25;众所周知,治愈等于致郁 34 16777215 210 25;那天留连的海岸 10 8700107 120 25;我将沉沦于二次元某个对立的街头,那是我所热衷于 2 15138834 330 25;此生无悔二次元,来世愿做画中人 110 15138834 30 25;烟花易逝人情长存 35 16777215 0 25;魈————! 57 16755202 30 25;你这话说的太真实了,单身使我们相遇 94 16777215 60 25;愿有一天你能和重要的人再次重逢 88 16777215 90 25;烟花从正面看是圆的,从侧面看是爱人的脸庞 5 16777215 180 25;你的名字 71 16777215 300 25;天气之子 63 16777215 150 25;最后来个萤火之森就绝杀了 78 16777215 330 25;懦夫表白墙 27 15138834 330 25;らららららららら 97 16777215 90 25;永远永远喜欢哈娜! 36 41194 0 25;依婷我爱你!!! 53 16777215 300 25;天气之子 63 16777215 300 25;八爷是神 13 16777215 60 25;所愿皆所得 10 52480 240 25;愿所愿皆所得 7 16777215 90 25;八爷!!!!!!! 38 15138834 150 25;八爷!!!!!! 26 15138834 210 25;希望跨过屏幕的界限,与你相遇在现实 41 16777215 180 25;蒂诺我喜欢你 19 16777215 60 25;谢谢 119 16777215 30 25;daoko声音好听 81 16777215 150 25;邵若燕我爱你 98 16777215 90 25;一转眼四年过去了(2024来) 23 15138834 330 25;记得我和你一起的时光 90 41194 210 25;[ohh] 70 16777215 300 25;真的超级好听啊!!! 0 15138834 60 25;if!!!!里面的if 54 16777215 330 25;天气之子 38 16777215 270 25;哈哈 35 16777215 240 25;夏舜妍活下去 58 16777215 150 25;拜托xsy活下去吧 46 16777215 330 25;故事里的她终成遗憾 25 16777215 60 25;[ohh] 68 16777215 210 25;再见他 45 16777215 90 25;5刷烟花了,神作 5 16777215 270 25;哦太平間褲衩味兒 6 16777215 240 25;姓赖的女孩,我要告诉你,很快我也要释怀啦 39 16777215 300 25;黎小茗我喜欢你 37 8700107 90 25;[前方高能] 29 16777215 0 25;金鱼来啦!!! 25 16740868 60 25;天气之子 63 16777215 240 25;gly我喜欢你 5 16777215 150 25;你的名字 73 16777215 210 25;吴润泽,抱歉啊! 58 41194 330 25;送你每一个盛夏 116 16777215 0 25;苏若优 33 16777215 90 25;你的名字 71 16777215 270 25;天气之子 63 16777215 240 25;llx。。我还是,一如以往四年般,喜欢你 56 16777215 120 25;李依琳我爱你 67 16777215 150 25;此生不悔二次元 34 41194 60 25;czh我爱你 44 16777215 120 25;秒速五厘米 34 16777215 300 25;烟花 31 16777215 150 25;陈思维!!!!! 58 16777215 180 25;贾若溪,我喜欢你 85 16646914 210 25;你的名字 71 16777215 150 25;你的名字 72 16777215 240 25;[ohh] 66 16777215 0 25;"
set FFMPEG_CMD=ffplay -i "%VIDEO_FILE%" -vf "
for %%A in ("%TEXT_INFO:;=";"%") do (
::echo Processing: %%~A
set count=0
for %%B in (%%~A) do (
set /a count+=1
set "ITEM!count!=%%~B"
)
:: FreeSerif.ttf
set "FFMPEG_CMD=!FFMPEG_CMD!drawtext=fontsize=!ITEM5!:text='!ITEM1!':x=w-100*(t-!ITEM2!):y=!ITEM4!:enable=gt(t\,!ITEM2!),"
)
set FFMPEG_CMD=!FFMPEG_CMD:~0,-1!"
!FFMPEG_CMD!
endlocal
可以先生成一段视频, 然后在继续前面的操作
@echo off
setlocal enabledelayedexpansion
set VIDEO_FILE=hy.mp4
set "TEXT_INFO=⭐———————— 27 16777215 300 25;我在叙利亚都没受过这么重的伤 107 16776960 270 25;底部淡蓝色字幕菌施工完毕,感谢欣赏 96 8700107 270 25;“升空的烟火,是圆的,还是扁的?”“圆的也好,扁的也好,奇怪形状也罢。只要我们俩在一起,什么我都不在乎。” 35 16646914 30 25;烟花易逝,人情长存 3 16707842 270 25;樱花易逝,春树常绿,以声之色,塑以花之形,将你之名,刻之我心。 75 16777215 270 25;赶快去表白,别留遗憾!!! 55 16646914 30 25;君(きみ)の後(うし)ろ姿(すがた)你留下背影的那天 15 9033215 300 25;焰色反应() 26 16707842 240 25;此时,西片正在找高木 99 15138834 270 25;底部淡蓝色中文字幕君开始施工,并非翻译 7 8700107 240 25;2022中考顺利!加油!! 35 16707842 270 25;↑说句人话:我爱你西宫硝子↑ 38 16776960 180 25;两年了,我已经放下啦 20 16707842 300 25;烟花易逝,人情长存 13 15138834 0 25;烟花易逝,人情长存 91 16777215 300 25;每当听到这首歌我心里就百感交集 34 16776960 0 25;烟花易逝,人情长存 0 16776960 180 25;此生无悔二次元,来世还做纸片人 116 15138834 60 25;还能坚持下去等一个人吗,已经错过了一整个青春 31 16777215 90 25;宋老师,您一定要幸福,我才不会遗憾 5 8700107 210 25;把灯火都灭掉,拨动寒冷的月光 66 16765698 180 25;打上军火 0 6830715 30 25;有情人终成兄妹(狗头) 110 15138834 270 25;等到有彩虹,你的脸亮起美丽的容光 40 16765698 90 25;这懵懂的感情在内心迸发 31 16765698 210 25;众所周知,治愈等于致郁 34 16777215 210 25;那天留连的海岸 10 8700107 120 25;我将沉沦于二次元某个对立的街头,那是我所热衷于 2 15138834 330 25;此生无悔二次元,来世愿做画中人 110 15138834 30 25;烟花易逝人情长存 35 16777215 0 25;魈————! 57 16755202 30 25;你这话说的太真实了,单身使我们相遇 94 16777215 60 25;愿有一天你能和重要的人再次重逢 88 16777215 90 25;烟花从正面看是圆的,从侧面看是爱人的脸庞 5 16777215 180 25;你的名字 71 16777215 300 25;天气之子 63 16777215 150 25;最后来个萤火之森就绝杀了 78 16777215 330 25;懦夫表白墙 27 15138834 330 25;らららららららら 97 16777215 90 25;永远永远喜欢哈娜! 36 41194 0 25;依婷我爱你!!! 53 16777215 300 25;天气之子 63 16777215 300 25;八爷是神 13 16777215 60 25;所愿皆所得 10 52480 240 25;愿所愿皆所得 7 16777215 90 25;八爷!!!!!!! 38 15138834 150 25;八爷!!!!!! 26 15138834 210 25;希望跨过屏幕的界限,与你相遇在现实 41 16777215 180 25;蒂诺我喜欢你 19 16777215 60 25;谢谢 119 16777215 30 25;daoko声音好听 81 16777215 150 25;邵若燕我爱你 98 16777215 90 25;一转眼四年过去了(2024来) 23 15138834 330 25;记得我和你一起的时光 90 41194 210 25;[ohh] 70 16777215 300 25;真的超级好听啊!!! 0 15138834 60 25;if!!!!里面的if 54 16777215 330 25;天气之子 38 16777215 270 25;哈哈 35 16777215 240 25;夏舜妍活下去 58 16777215 150 25;拜托xsy活下去吧 46 16777215 330 25;故事里的她终成遗憾 25 16777215 60 25;[ohh] 68 16777215 210 25;再见他 45 16777215 90 25;5刷烟花了,神作 5 16777215 270 25;哦太平間褲衩味兒 6 16777215 240 25;姓赖的女孩,我要告诉你,很快我也要释怀啦 39 16777215 300 25;黎小茗我喜欢你 37 8700107 90 25;[前方高能] 29 16777215 0 25;金鱼来啦!!! 25 16740868 60 25;天气之子 63 16777215 240 25;gly我喜欢你 5 16777215 150 25;你的名字 73 16777215 210 25;吴润泽,抱歉啊! 58 41194 330 25;送你每一个盛夏 116 16777215 0 25;苏若优 33 16777215 90 25;你的名字 71 16777215 270 25;天气之子 63 16777215 240 25;llx。。我还是,一如以往四年般,喜欢你 56 16777215 120 25;李依琳我爱你 67 16777215 150 25;此生不悔二次元 34 41194 60 25;czh我爱你 44 16777215 120 25;秒速五厘米 34 16777215 300 25;烟花 31 16777215 150 25;陈思维!!!!! 58 16777215 180 25;贾若溪,我喜欢你 85 16646914 210 25;你的名字 71 16777215 150 25;你的名字 72 16777215 240 25;[ohh] 66 16777215 0 25;"
set FFMPEG_CMD=ffmpeg -i "%VIDEO_FILE%" -vf "
for %%A in ("%TEXT_INFO:;=";"%") do (
::echo Processing: %%~A
set count=0
for %%B in (%%~A) do (
set /a count+=1
set "ITEM!count!=%%~B"
)
set "FFMPEG_CMD=!FFMPEG_CMD!drawtext=fontsize=!ITEM5!:text='!ITEM1!':x=w-100*(t-!ITEM2!):y=!ITEM4!:enable=gt(t\,!ITEM2!),"
)
set FFMPEG_CMD=!FFMPEG_CMD:~0,-1!"
:: 视频输出
!FFMPEG_CMD! output.mp4
这里的中文输出可能会有乱码, 在cmd中输入chcp 65001
, 就可以切换为UTF-8模式
弹幕提取
比如bilibili的, 可以通过网址获取, 我想要的是https://comment.bilibili.com/215991800.xml, 这里面是xml文件, 先将文件下载下来, 然后使用任何一门编程语言做xml解析, 我使用的是java
package com.wpl.tool;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
import java.util.Random;
public class DOMParser {
static StringBuilder stringBuilder = new StringBuilder();
static int unit = 30;
static int height = 360;
static int count = height/unit;
static int duration = 120;
static int durationD = 289;
public static void main(String[] args) {
int c = 0;
stringBuilder.append("set \"TEXT_INFO=");
try {
File xmlFile = new File("src/main/resources/215991800.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
//System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
NodeList nodeList = doc.getElementsByTagName("d");
//System.out.println("nodeList.getLength() "+nodeList.getLength());
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
Element element = (Element) node;
//System.out.println(node.getTextContent());
String p = element.getAttribute("p");
String[] strings = p.split(",");
String context = node.getTextContent();
String startTime0 = strings[0];
String[] preStartTime = startTime0.split("\\.");
int startTime = Integer.parseInt(preStartTime[0])*duration/durationD;
// Integer.parseInt(strings[2])+height+""
String fontSize =strings[2];
Random random = new Random();
int randomNumber = random.nextInt(count);
String y = randomNumber*unit+"";
String color = strings[3]; //十六进制
color = Integer.toHexString(Integer.parseInt(color));
while(color.length()!=6){
color = "0"+color;
}
context = context.replace(" ", "");
context = context.replace(",", ",");
c++;
stringBuilder.append(context+" "+startTime +" "+"#"+color+" "+y+" "+fontSize+";");
if(c==100){
stringBuilder.append("\"");
System.out.println(stringBuilder.toString());
c=0;
stringBuilder.setLength(0);
stringBuilder.append("set \"TEXT_INFO=");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
最后结果为这个样子