Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ffmpeg:检查视频文件夹与bash文件的一致性_Bash_Video_Ffmpeg_Mpeg Dash - Fatal编程技术网

ffmpeg:检查视频文件夹与bash文件的一致性

ffmpeg:检查视频文件夹与bash文件的一致性,bash,video,ffmpeg,mpeg-dash,Bash,Video,Ffmpeg,Mpeg Dash,我编写了一个小的bash文件,用于读取文件夹、生成播放列表、连接、添加徽标并对dash ready的大视频结果进行编码,我希望通过检查所有视频的一致性来实现它:它们是否具有相同的fps、相同的分辨率、相同的时基等。 以下是我的情况: #!/bin/bash # CONCAT DEMUXER #This demuxer reads a list of #files and other directives from a text file and demuxes them one after th

我编写了一个小的bash文件,用于读取文件夹、生成播放列表、连接、添加徽标并对dash ready的大视频结果进行编码,我希望通过检查所有视频的一致性来实现它:它们是否具有相同的fps、相同的分辨率、相同的时基等。 以下是我的情况:

#!/bin/bash
# CONCAT DEMUXER
#This demuxer reads a list of #files and other directives from a text file and demuxes them one after the other, as if #all their packets had been muxed together. All files must have the same streams (same #codecs, same time base, etc.) but can be wrapped in different container formats.

times=()
for f in *.mp4; do
    _t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
    times+=("$_t")
done
TOTALDURATION=$( echo "${times[@]}" | sed 's/ /+/g' | bc )


printf "file '%s'\n" *.mp4 > playlist.txt
ffmpeg -auto_convert 1 -f concat -safe 0 -i playlist.txt -c:a aac -b:a 384k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts 'keyint=50:min-keyint=50:no-scenecut' -r 25 -b:v 2400k -maxrate 2400k -bufsize 1200k -vf "scale=-1:432" -vf "movie=stable.png [watermark]; [in][watermark] overlay=main_w-overlay_w-10:10 [out]" -t $TOTALDURATION out.mp4
#clear
echo “VIDEO CONCAT COMPLETED”
例如,我在下面找到了这个bash,它计算文件夹的总持续时间(以秒为单位)

times=()
for f in *.mp4; do
    _t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
    times+=("$_t")
done
TOTALDURATION=$( echo "${times[@]}" | sed 's/ /+/g' | bc )
我希望在处理之前检查视频是否具有相同的fps和相同的分辨率 谢谢 马西莫

Bash 有人在这个问题中发布了一个获取视频持续时间的示例:

他的做法是:

ffmpeg -i input.mp4 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//
在我看来,您应该使用ffprobe而不是ffmpeg。更好的语法:

ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
以下是一些很好的例子:

您可以将第一个视频的结果保存在变量中,并将所有其他视频与第一个视频进行比较。 如果需要,可以给你更多的例子

但我可以推荐另一种方式:nodejs

NodeJS 如果您熟悉JavaScript,只需编写一个NodeJS脚本。在我看来,代码更容易编写

您需要安装NodeJS。在您的项目中,使用
npm安装安装fluent-ffmpeg——保存fluent-ffmpeg

在您选择的js文件中编写脚本,并使用
node script.js
从bash脚本运行脚本

从视频文件中查找所需信息的代码段如下所示:

var ffmpeg = require('fluent-ffmpeg');

ffmpeg.ffprobe('./input.mp4', function(err, metadata) {
    //console.dir(metadata); // all metadata
    console.log(metadata.format.duration);
    console.log(metadata.streams[0].width);
    console.log(metadata.streams[0].height);
    console.log(metadata.streams[0].r_frame_rate);
    console.log(metadata.streams[0].time_base);
    //... use first console.dir to get all possible informations
});
更新BASH 下面是一个完整的示例,用于将目录中的所有mp4视频转换为输出目录,并在以下情况下连接它们:

#!/bin/bash

SCALE="768:432"
FPS="25"

mkdir -p ./output/

for i in *.mp4;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -i "$i" -c:v libx264 -preset slow -crf 22 -vf scale=$SCALE -framerate $FPS -c:a aac -b:a 128k -f mp4 "output/${name}.mp4";
done

printf "file '%s'\n" ./output/*.mp4 > ./playlist.txt

ffmpeg -f concat -safe 0 -i ./playlist.txt -c copy ./output/concat.mp4
  • 宽度、高度和帧速率设置为定义的值,以使连接成为可能
  • 视频编码的预设很慢,所以重新编码非常慢;)
  • 如有必要,可以将音频比特率增加,例如增加到192k
Bash 有人在这个问题中发布了一个获取视频持续时间的示例:

他的做法是:

ffmpeg -i input.mp4 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//
在我看来,您应该使用ffprobe而不是ffmpeg。更好的语法:

ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
以下是一些很好的例子:

您可以将第一个视频的结果保存在变量中,并将所有其他视频与第一个视频进行比较。 如果需要,可以给你更多的例子

但我可以推荐另一种方式:nodejs

NodeJS 如果您熟悉JavaScript,只需编写一个NodeJS脚本。在我看来,代码更容易编写

您需要安装NodeJS。在您的项目中,使用
npm安装安装fluent-ffmpeg——保存fluent-ffmpeg

在您选择的js文件中编写脚本,并使用
node script.js
从bash脚本运行脚本

从视频文件中查找所需信息的代码段如下所示:

var ffmpeg = require('fluent-ffmpeg');

ffmpeg.ffprobe('./input.mp4', function(err, metadata) {
    //console.dir(metadata); // all metadata
    console.log(metadata.format.duration);
    console.log(metadata.streams[0].width);
    console.log(metadata.streams[0].height);
    console.log(metadata.streams[0].r_frame_rate);
    console.log(metadata.streams[0].time_base);
    //... use first console.dir to get all possible informations
});
更新BASH 下面是一个完整的示例,用于将目录中的所有mp4视频转换为输出目录,并在以下情况下连接它们:

#!/bin/bash

SCALE="768:432"
FPS="25"

mkdir -p ./output/

for i in *.mp4;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -i "$i" -c:v libx264 -preset slow -crf 22 -vf scale=$SCALE -framerate $FPS -c:a aac -b:a 128k -f mp4 "output/${name}.mp4";
done

printf "file '%s'\n" ./output/*.mp4 > ./playlist.txt

ffmpeg -f concat -safe 0 -i ./playlist.txt -c copy ./output/concat.mp4
  • 宽度、高度和帧速率设置为定义的值,以使连接成为可能
  • 视频编码的预设很慢,所以重新编码非常慢;)
  • 如有必要,可以将音频比特率增加,例如增加到192k

嗨@Uwe你在想什么?是原始的,可以在代码经济的情况下编写更多代码,但似乎有效:

#!/bin/bash

times=()
fps=()
for f in *.mp4; do

   _t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
    times+=("$_t")

    _f=$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p")
    fps+=(“$_f”)
done

TOTALDURATION=$( echo "${times[@]}" | sed 's/ /+/g' | bc )

tLen=${#fps[@]}

for tLen in "${fps[@]:1}"; do
    if [[ $tLen != ${fps[0]} ]]; then
        printf “WARNING: VIDEO’S FRAME-RATE (fps) ARE NOT EQUALS, THE PROCESS CAN’T START.”
        printf "%s\0" "${fps[@]}" |
            sort -zu |
            xargs -0 printf " %s"
        printf "\n"
       exit 1
    fi
done

for f in *.mp4; do

DUR="$(ffmpeg -i "$f" 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@\..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }')"

FPS="$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p")"
FPSC=$( echo "($FPS+0.5)/1" | bc )

NAME=$(echo "$f" | cut -d'.' -f1)

GOP="$((FPSC*2))"
DURM="$((DUR%2))"
FDUR="$(($DUR-$DURM))"

ffmpeg -y -i "$f" -i logo.png -c:a aac -b:a 384k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts keyint=$GOP:min-keyint=$GOP:no-scenecut -bf 0 -r $FPSC -b:v 4800k -maxrate 4800k -bufsize 3000k -profile:v main -t $FDUR -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10,scale=1920:1080,setsar=1" ${NAME}-1080.mp4


ffmpeg -y -i ${NAME}-720.mp4 -c:a aac -b:a 128k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts keyint=$GOP:min-keyint=$GOP:no-scenecut -bf 0 -s 640x360 -r $FPSC -b:v 800k -maxrate 800k -bufsize 500k -profile:v main -t $FDUR ${NAME}-360.mp4
done

# with a bash for loop
for f in ./*1080.mp4; do echo "file '$f'" >> 1080list.txt; done
# or with printf
printf "file '%s'\n" ./*1080.mp4 > 1080list.txt

ffmpeg -f concat -safe 0 -i 1080list.txt -c copy 1080set.mp4

# with a bash for loop
for f in ./*360.mp4; do echo "file '$f'" >> 360list.txt; done
# or with printf
printf "file '%s'\n" ./*360.mp4 > 360list.txt

ffmpeg -f concat -safe 0 -i 360list.txt -c copy 360set.mp4

rm *1080.mp4
rm *.txt
rm *360.mp4

echo $TOTALDURATION

嗨,你在想什么?是原始的,可以在代码经济的情况下编写更多代码,但似乎有效:

#!/bin/bash

times=()
fps=()
for f in *.mp4; do

   _t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
    times+=("$_t")

    _f=$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p")
    fps+=(“$_f”)
done

TOTALDURATION=$( echo "${times[@]}" | sed 's/ /+/g' | bc )

tLen=${#fps[@]}

for tLen in "${fps[@]:1}"; do
    if [[ $tLen != ${fps[0]} ]]; then
        printf “WARNING: VIDEO’S FRAME-RATE (fps) ARE NOT EQUALS, THE PROCESS CAN’T START.”
        printf "%s\0" "${fps[@]}" |
            sort -zu |
            xargs -0 printf " %s"
        printf "\n"
       exit 1
    fi
done

for f in *.mp4; do

DUR="$(ffmpeg -i "$f" 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@\..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }')"

FPS="$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p")"
FPSC=$( echo "($FPS+0.5)/1" | bc )

NAME=$(echo "$f" | cut -d'.' -f1)

GOP="$((FPSC*2))"
DURM="$((DUR%2))"
FDUR="$(($DUR-$DURM))"

ffmpeg -y -i "$f" -i logo.png -c:a aac -b:a 384k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts keyint=$GOP:min-keyint=$GOP:no-scenecut -bf 0 -r $FPSC -b:v 4800k -maxrate 4800k -bufsize 3000k -profile:v main -t $FDUR -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10,scale=1920:1080,setsar=1" ${NAME}-1080.mp4


ffmpeg -y -i ${NAME}-720.mp4 -c:a aac -b:a 128k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts keyint=$GOP:min-keyint=$GOP:no-scenecut -bf 0 -s 640x360 -r $FPSC -b:v 800k -maxrate 800k -bufsize 500k -profile:v main -t $FDUR ${NAME}-360.mp4
done

# with a bash for loop
for f in ./*1080.mp4; do echo "file '$f'" >> 1080list.txt; done
# or with printf
printf "file '%s'\n" ./*1080.mp4 > 1080list.txt

ffmpeg -f concat -safe 0 -i 1080list.txt -c copy 1080set.mp4

# with a bash for loop
for f in ./*360.mp4; do echo "file '$f'" >> 360list.txt; done
# or with printf
printf "file '%s'\n" ./*360.mp4 > 360list.txt

ffmpeg -f concat -safe 0 -i 360list.txt -c copy 360set.mp4

rm *1080.mp4
rm *.txt
rm *360.mp4

echo $TOTALDURATION

感谢Uwe,我多次听说node.js,但我从未研究过它,正如你所知,我想在一个bash文件中集成所有必要的操作,以使视频concat准备就绪,但我首先遇到了有关音频视频同步的问题:因为不是所有视频都有音频轨道,只要视频,我使用ffmpeg上的-t剪切它们,使其以i帧结束,但如果有多个视频出现此问题,则会导致音视频同步出现故障,我希望解释我自己。。出于这个原因,我认为暂时放弃这个意图太难实现自动化me@MassimoVantaggio不要放弃,这并不像你想的那么难。无需验证相同的参数,只需重新编码所有视频。我发布了一个完整的bash脚本示例,请参见更新的答案。使用您提供的两个视频进行测试,效果良好。只需在包含输入视频的目录中运行脚本,就可以在输出文件夹中获得concat.mp4。重新调节需要一些时间…您希望我在调试完媒体服务器后立即学习node.js。。谢谢你,我们!感谢Uwe,我多次听说node.js,但我从未研究过它,正如你所知,我想在一个bash文件中集成所有必要的操作,以使视频concat准备就绪,但我首先遇到了有关音频视频同步的问题:因为不是所有视频都有音频轨道,只要视频,我使用ffmpeg上的-t剪切它们,使其以i帧结束,但如果有多个视频出现此问题,则会导致音视频同步出现故障,我希望解释我自己。。出于这个原因,我认为暂时放弃这个意图太难实现自动化me@MassimoVantaggio不要放弃,这并不像你想的那么难。无需验证相同的参数,只需重新编码所有视频。我发布了一个完整的bash脚本示例,请参见更新的答案。使用您提供的两个视频进行测试,效果良好。只需在包含输入视频的目录中运行脚本,就可以在输出文件夹中获得concat.mp4。重新调节需要一些时间…您希望我在调试完媒体服务器后立即学习node.js。。谢谢你,我们!你应该检查你的脚本。它将帮助你发现问题。谢谢,我只是尝试一下。你应该检查你的脚本。它会帮你找到问题。谢谢,我只是试试