Ffmpeg: Concat multiple videos and an audio file. Videos may or may not have audio and I cant know it before runnign the command

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

Ffmpeg: Concat multiple videos and an audio file. Videos may or may not have audio and I cant know it before runnign the command

问题

我有一个MP4文件列表和一个AAC音频文件。我有一个名为concat.txt的文件,其中包含需要连接的所有MP4文件。

我需要将所有MP4文件连接起来,并将AAC音频合并到顶部。

正如标题所述,单独的MP4文件可能具有或不具有音频轨道,而且我无法检查没有音频的MP4文件,因为这将是每天执行成千上万次命令的自动化过程。

如果存在MP4的声音,则必须保留并与AAC合并。

以下是适用于至少我的MP4文件中的第一个具有音频轨道的情况的工作命令:

ffmpeg -f concat -safe 0 -i concat.txt -i audio.aac  -c:v copy -filter_complex "[0:a][1:a] amix=inputs=2:duration=shortest [audio_out]" -map 0:v -map "[audio_out]" -y result.mp4

但是,如果我的MP4文件没有音频,这个命令会失败:

在过滤图描述中的流指定符 ':a' [0:a][1:a] amix=inputs=2:duration=shortest [audio_out] 不匹配任何流。

我一直在阅读关于anullsrc的内容,并希望获取[0:a](如果存在)或生成的空音频通道,并将其与我的AAC合并,但我还没有成功。

任何帮助都将不胜感激。

谢谢。

英文:

I have a list of mp4 and an aac audio file. I have a concat.txt file with all the mp4s that need to be concatenated.
I need to concat all the mp4s and merge the aac on top.

As said in the title, the mp4s individually may or may not have an audio track, and I can not check the mp4s with no audio, add a dummy sound track as it will be an automated process with thousands of commands executed daily.

The sound of the mp4, if present, must be preserved and merged with the aac

Here is a working command for the case where at least the first of my mp4s has an audiotrack:

ffmpeg -f concat -safe 0 -i concat.txt -i audio.aac  -c:v copy -filter_complex "[0:a][1:a] amix=inputs=2:duration=shortest [audio_out]" -map 0:v -map "[audio_out]" -y result.mp4

However that breaks if my mp4s dont have audio

> Stream specifier ':a' in filtergraph description [0:a][1:a]
> amix=inputs=2:duration=shortest [audio_out] matches no streams.

I've been reading about anullsrc, and would like to take [0:a] if it exists, or a generated empty audio channel, and merge it with my aac, but I'm not getting there.

Any help would be appreciated

Thanks

答案1

得分: 1

#!/bin/bash
LST=("input 1.mp4" "only_video.mp4" "1280x720x30_2.mp4")
f="${LST[0]}"

IFS=, read VID WID HEI SAR FMT FPS TBN <<< $(ffprobe -v 0 -select_streams v:0 -show_entries stream=codec_name,width,height,sample_aspect_ratio,r_frame_rate,time_base,pix_fmt -of csv=p=0 "$f")
echo $VID $WID $HEI $SAR $FMT $FPS $TBN
if [ "$SAR" = "N/A" ]; then SAR=1; fi
TBN=${TBN#*/}
echo $VID $WID $HEI $SAR $FMT $FPS $TBN

IFS=, read AUD SRA CHL <<< $(ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name,channel_layout,sample_rate -of csv=p=0 "$f")
echo $AUD $SRA $CHL

TXT=list.txt
mkdir out
o="out/${f%.*}.mkv"
ffmpeg -i "$f" -c copy "$o" -y -hide_banner
echo "file '$o'" > $TXT

for (( i=1; i<${#LST[@]}; i++ )); do
  f="${LST[$i]}"
  o="out/${f%.*}.mkv"
  AU2=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$f")
  if [ "$AU2" = "" ]; then
    echo --- create empty audio
    ffmpeg -i "$f" -f lavfi -i anullsrc -c:v copy -c:a $AUD -q:a 5 -shortest "$o" -y -hide_banner
  else
    if [ "$AU2" = "$AUD" ]; then
      echo --- copy audio
      ffmpeg -i "$f" -c copy "$o" -y -hide_banner
    else
      echo --- encode audio
      ffmpeg -i "$f" -c:v copy -c:a $AUD -q:a 5 -shortest "$o" -y -hide_banner
    fi
  fi
  echo "file '$o'" >> $TXT
done

cat "$TXT"
ffmpeg -f concat -safe 0 -i "$TXT" -i "input 3.mp3" -filter_complex "
[0:a][1:a] amix=inputs=2:duration=shortest
" -c:v copy -c:a aac out/output.mp4 -y -hide_banner

mpv out/output.mp4
英文:

bash script

#!/bin/bash
#LST=($(ls -1tr *.mp4))
LST=(&quot;input 1.mp4&quot; &quot;only_video.mp4&quot; &quot;1280x720x30_2.mp4&quot;)
#LST=(&quot;1280x720x30_1.mp4&quot; &quot;only_video.mp4&quot; &quot;1280x720x30_2.mp4&quot;)
f=&quot;${LST[0]}&quot;
IFS=, read VID WID HEI SAR FMT FPS TBN &lt;&lt;&lt; $(ffprobe -v 0 -select_streams v:0 -show_entries stream=codec_name,width,height,sample_aspect_ratio,r_frame_rate,time_base,pix_fmt -of csv=p=0 &quot;$f&quot;)
echo $VID $WID $HEI $SAR $FMT $FPS $TBN
if [ &quot;$SAR&quot; = &quot;N/A&quot; ]; then SAR=1; fi
#FPS=30
TBN=${TBN#*/}
echo $VID $WID $HEI $SAR $FMT $FPS $TBN
IFS=, read AUD SRA CHL &lt;&lt;&lt; $(ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name,channel_layout,sample_rate -of csv=p=0 &quot;$f&quot;)
echo $AUD $SRA $CHL
TXT=list.txt
mkdir out
o=&quot;out/${f%.*}.mkv&quot;
ffmpeg -i &quot;$f&quot; -c copy &quot;$o&quot; -y -hide_banner
echo &quot;file &#39;$o&#39;&quot; &gt; $TXT
for (( i=1; i&lt;${#LST[@]}; i++ )); do
f=&quot;${LST[$i]}&quot;
o=&quot;out/${f%.*}.mkv&quot;
AU2=$(ffprobe -v 0 -select_streams a:0 -show_entries stream=codec_name -of default=nw=1:nk=1 &quot;$f&quot;)
if [ &quot;$AU2&quot; = &quot;&quot; ]; then
echo --- create empty audio
ffmpeg -i &quot;$f&quot; -f lavfi -i anullsrc -c:v copy -c:a $AUD -q:a 5 -shortest &quot;$o&quot; -y -hide_banner
else
if [ &quot;$AU2&quot; = &quot;$AUD&quot; ]; then
echo --- copy audio
ffmpeg -i &quot;$f&quot; -c copy &quot;$o&quot; -y -hide_banner
else
echo --- encode audio
ffmpeg -i &quot;$f&quot; -c:v copy -c:a $AUD -q:a 5 -shortest &quot;$o&quot; -y -hide_banner
fi
fi
echo &quot;file &#39;$o&#39;&quot; &gt;&gt; $TXT
done
cat &quot;$TXT&quot;
ffmpeg -f concat -safe 0 -i &quot;$TXT&quot; -i &quot;input 3.mp3&quot; -filter_complex &quot;
[0:a][1:a] amix=inputs=2:duration=shortest
&quot; -c:v copy -c:a aac out/output.mp4 -y -hide_banner
mpv out/output.mp4

it was simplified and edited part of script

huangapple
  • 本文由 发表于 2023年7月27日 21:21:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76780189.html
匿名

发表评论

匿名网友

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

确定