英文:
how to put a red frame before each video programmatically, when concatenating videos using ffmpeg
问题
要使用ffmpeg合并文件,我创建一个类似这样的文本文件:
file 'a.mkv'
file 'b.mkv'
file 'c.mkv'
然后,我运行以下命令来连接这些视频:
ffmpeg -f concat -i file.txt -c copy merged.mkv
但问题是,我想在每个视频的中间放置一个三秒的红色帧。
现在,我可以获取这些视频的帧尺寸,并创建一个视频,然后修改文本文件如下:
file 'red.mkv'
file 'a.mkv'
file 'red.mkv'
file 'b.mkv'
file 'red.mkv'
file 'c.mkv'
但这不是一种编程方法,所以是否有任何方法可以合并视频并在每个视频之前插入三秒的红色帧?
我想在运行时生成那个红色帧视频。
英文:
To merge files with ffmpeg I'm creating a text file like this:
file 'a.mkv'
file 'b.mkv'
file 'c.mkv'
Then I'm running this command to concat these videos:
ffmpeg -f concat -i file.txt -c copy merged.mkv
But the thing is, I want to put red frame for three seconds in the middle of each video.
Now I can get these videos' frame dimensions and create a video and modify the text file like this:
file 'red.mkv'
file 'a.mkv'
file 'red.mkv'
file 'b.mkv'
file 'red.mkv'
file 'c.mkv'
But this is not a programmatical approach, so is there any way I can concat videos and put red frames for three seconds (before every video)?
I want to generate that red frame video, on run time.
答案1
得分: 1
这是您的代码的翻译部分:
#!/bin/bash
intro=a.mkv
main=b.mkv
outro=c.mkv
red=red.mkv
VID=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$main")
WID=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=width -of default=nw=1:nk=1 "$main")
HEI=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=height -of default=nw=1:nk=1 "$main")
SAR=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=sample_aspect_ratio -of default=nw=1:nk=1 "$main")
if [ "$SAR" = "N/A" ]; then SAR=1; fi
FPS=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=r_frame_rate -of default=nw=1:nk=1 "$main")
# 如果视频具有可变帧率,可能会得到类似 22840/769 的值
FPS=30
TBN=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=time_base -of default=nw=1:nk=1 "$main")
TBN=${TBN#*/}
FMT=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=pix_fmt -of default=nw=1:nk=1 "$main")
echo $VID $WID $HEI $SAR $FPS $TBN $FMT
AUD=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$main")
CHL=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=channel_layout -of default=nw=1:nk=1 "$main")
SRA=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=sample_rate -of default=nw=1:nk=1 "$main")
echo $AUD $CHL $SRA
ffmpeg \
-f lavfi -i "color=c=red:s=${WID}x${HEI}:r=${FPS}:d=3" \
-f lavfi -i "anullsrc=cl=$CHL:r=$SRA" \
-c:v $VID -c:a $AUD -video_track_timescale $TBN -shortest $red -y
echo --- "$red"
ffprobe -v 0 -select_streams v:0 -show_entries stream=codec_name,width,height,sample_aspect_ratio,r_frame_rate,avg_frame_rate,time_base,pix_fmt -of csv=print_section=0 "$red"
ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name,sample_rate,channels -of csv=print_section=0 "$red"
l="list.txt"
echo "file '$intro'" > $l
for f in $main $outro; do
[[ ! -f $f ]] && continue
echo "file '$red'" >> $l
echo "file '$f'" >> $l
done
cat $l
ffmpeg -f concat -i list.txt -c copy output.mp4 -y
mpv output.mp4
这只是您代码的翻译部分,没有额外的内容。如果您需要任何进一步的帮助或修改,请提出具体的问题。
英文:
bash script:
#!/bin/bash
intro=a.mkv
main=b.mkv
outro=c.mkv
red=red.mkv
VID=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$main")
WID=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=width -of default=nw=1:nk=1 "$main")
HEI=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=height -of default=nw=1:nk=1 "$main")
SAR=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=sample_aspect_ratio -of default=nw=1:nk=1 "$main")
if [ "$SAR" = "N/A" ]; then SAR=1; fi
FPS=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=r_frame_rate -of default=nw=1:nk=1 "$main")
# if video has variable framerate, you can get something like 22840/769
FPS=30
TBN=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=time_base -of default=nw=1:nk=1 "$main")
TBN=${TBN#*/}
FMT=$(ffprobe -v 0 -select_streams v:0 -show_entries stream=pix_fmt -of default=nw=1:nk=1 "$main")
echo $VID $WID $HEI $SAR $FPS $TBN $FMT
AUD=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$main")
CHL=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=channel_layout -of default=nw=1:nk=1 "$main")
SRA=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=sample_rate -of default=nw=1:nk=1 "$main")
echo $AUD $CHL $SRA
ffmpeg \
-f lavfi -i "color=c=red:s=${WID}x${HEI}:r=${FPS}:d=3" \
-f lavfi -i "anullsrc=cl=$CHL:r=$SRA" \
-c:v $VID -c:a $AUD -video_track_timescale $TBN -shortest $red -y
echo --- "$red"
ffprobe -v 0 -select_streams v:0 -show_entries stream=codec_name,width,height,sample_aspect_ratio,r_frame_rate,avg_frame_rate,time_base,pix_fmt -of csv=print_section=0 "$red"
ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name,sample_rate,channels -of csv=print_section=0 "$red"
l="list.txt"
echo "file '$intro'" > $l
for f in $main $outro; do
[[ ! -f $f ]] && continue
echo "file '$red'" >> $l
echo "file '$f'" >> $l
done
cat $l
ffmpeg -f concat -i list.txt -c copy output.mp4 -y
mpv output.mp4
maybe, you have to add something to this code
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论