how to put a red frame before each video programmatically, when concatenating videos using ffmpeg

huangapple go评论62阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年2月6日 22:00:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75362304.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定