合并多个视频并获取子视频时间节点【ffmpeg】

583 阅读3分钟

1. 创建合并文件脚本 vmerger

移动所有子文件夹中.mp4文件到目录下

find ./ -name "*.mp4" | xargs -I file mv file ./

使用ls:无法指定mp4文件类型

ls | awk '{print "file '\''" $7 "'\''"}' > vmerger.txt

使用find:排序不太准

find . -type f -name "*.mp4" | sort | awk '{sub(/\.\//,""); print "file '\''" $1 "'\''"}' > vmerger

2. 合并视频

ffmpeg -f concat -safe 0 -i vmerger -c copy output.mp4

3. 倍速视频(1.25倍速:v反向0.8,a正向1.25)

ffmpeg -i output.mp4 -filter_complex "[0:v]setpts=0.8*PTS[v];[0:a]atempo=1.25[a]" -map "[v]" -map "[a]" outputX.mp4  

4. 创建章节时间点信息(注意命名不能出现空格)

echo 'l=$(ffmpeg -i $1 2>&1 | grep 'Duration' | cut -d "'" "'" -f 4 | sed s/,//);echo "${1:2} ${l:0:8}"' > ./ff
chmod +x ./ff
find . -type f -name "*.mp4" | sort | awk '{system("./ff " $1)}' > time.txt

5. 知识点总结(选看)

1、shell中echo使用单引号时输出单引号

[root@db01 ~] echo 'hello'"'"'world'
hello'world

2、Shell字符串截取(非常详细)

格式说明
${string:start:length}从string字符串的左边第start个字符开始,向右截取length个字符
${string:start}从string字符串的左边第start个字符开始截取,直到最后
${string:0-start:length}从string字符串的右边第start个字符开始,向右截取length个字符
${string:0-start}从string字符串的右边第start个字符开始截取,直到最后
${string#*chars}从string字符串第一次出现chars的位置开始,截取chars右边的所有字符
${string##*chars}从string字符串最后一次出现chars的位置开始,截取chars右边的所有字符
${string%chars*}从string字符串第一次出现chars的位置开始,截取chars左边的所有字符
${string%%chars*}从string字符串最后一次出现chars的位置开始,截取chars左边的所有字符

3、awk输出单引号,双引号

双引号:

awk '{print "\""}'        #放大:awk '{print "  \"  "}'

使用“”双引号把一个双引号括起来,然后用转义字符\对双引号进行转义,输出双引号。

单引号:

awk '{print "'\''"}'       # 放大: awk '{print  "  '  \  '  '   " }'

使用一个双引号“”,然后在双引号里面加入两个单引号‘’,接着在两个单引号里面加入一个转义的单引号',输出单引号。

4、在awk中执行system命令------太有用了

有这样一个临时需求: 在a.txt文件中有一万行字符串, 而二进制文件test能解密任何一行, 格式为./test decrypt xxx, 现在要把a.txt的所有行解密出来, 存放在b.txt, 怎么搞?

我一开始的思路是: 写程序逐行读取a.txt, 然后在程序中循环执行system("./test decrypt xxx"), 看看, 这是多个SB的事情啊。 为什么不用awk + system快速搞起呢?

ubuntu@VM-0-13-ubuntu:~$ cat a.txt
abc
def
ok
ubuntu@VM-0-13-ubuntu:~$ awk '{cmd="echo hehe "$0; system(cmd)}' a.txt
hehe abc
hehe def
hehe ok
ubuntu@VM-0-13-ubuntu:~$ 

所以, 在我那个实际例子, 可以这么搞:

awk '{cmd="./test decrypt "$0; system(cmd)}' a.txt  > b.txt

本来以为要半个小时, 结果5分钟搞定。

5、awk substr 左、右取字符

从左截取参考

substr($4,20)     --->  表示是从第4个字段里的第20个字符开始,一直到设定的分隔符","结束.
substr($3,12,8)   --->  表示是从第3个字段里的第12个字符开始,截取8个字符结束.

#示例:
$echo "this is a test,test" |awk -F',' '{print substr($1,1,4)"," substr($2,1) } '     //以,为分隔符,取第一子串的从第一个字符开始的4个字符和第二子串的第一个字符开始的全部字符,且以“,”分割符打印输出
this,test

从右截取参考

awk '{print substr($0,1,length($0)-4)}'   //表示对整个字符串,取去掉自右开始的4个字符后的字符串

# 示例:
$echo "this is a test,test" |awk '{print substr($0,1,length($0)-4)}'             
this is a test,
$echo "this is a test,test" |awk -F, '{print substr($1,length($1)-0)}'      //取自右开始的第一个字符
t
$echo "this is a test,test" |awk -F, '{print substr($1,length($1)-1)}'   //取自右开始的前两个字符
st
$echo "this is a test,test"|awk '{print length($0)}'   // 获取字符串长度

带有目录的字符串

 $echo 'z:\testPath\te_120200\' | awk '{print length($0)}'		//双引号和不加引号都不能达到识别字符串的目的

6、不使用 ffmpeg 命令读取mp4视频时长

大家一般都用 ffmpeg 获取视频长度,今天看到有一个 mediainfo 也有这个功能。

ffmpeg 命令是

ffmpeg -i test.flv 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//
#或者
ffprobe -v quiet -select_streams v -show_entries stream=duration -of csv=“p=0” foo.mp4

视频的时长有多个值,分别是容器时长、音视频流时长、解码后播放时长,这几个值可能不一样,就导致了不同播放器显示值不一样,不同播放时也因此表现得不一样。如果发现容器或流的持续时间丢失或不准确(可能由于文件损坏或被截断),则可能需要完全解码输入。

centos 7 安装 mediainfo

yum install mediainfo -y

MacOS 安装 mediainfo

brew install mediainfo

mediainfo 将以毫秒为单位的持续时间输出为单个整数值。

mediainfo --Output='General;%Duration%' file.mp4

批量查找目录下所有mp4 文件并打印时长

#!/bin/sh

echo 'l=$(mediainfo --Output="General;%Duration%" $1);echo "$1:$l"' > ~/ff
chmod +x ~/ff
find . -type f -name "*.mp4" | awk '{system("~/ff " $1)}'

7、以下FFmpeg命令我都实际操作可用,拿去使用改下名称即可

合并视频 vfilelist是文本文件,格式如图,将output.mp4追加合并后输出为 outlast.mp4 ![在这里插入图片描述](img-blog.csdnimg.cn/940991c55ce… =300x)

ffmpeg -f concat -i vfilelist -c copy outlast.mp4

wav音频转为mp3

ffmpeg -i input.m4a output.mp3

2个音频合并

ffmpeg -i 音频1.mp3 -i 音频2.mp3 -filter_complex '[0:0] [1:0] concat=n=2:v=0:a=1 [a]' -map [a] result.mp3

3个音频合并

ffmpeg -i 音频1.wav -i 音频2.WAV -i 音频3.wav -filter_complex '[0:0] [1:0] [2:0] concat=n=3:v=0:a=1 [a]' -map [a] mresult.wav
ffmpeg -i fenweikong.mp3 -i fenweikong.mp3 -i fenweikong.mp3 -filter_complex '[0:0] [1:0] [2:0] concat=n=3:v=0:a=1 [a]' -map [a] mresult.mp3

合并音频和视频,复制音频(需要重新编码)

ffmpeg -i 视频.mp4 -i 音频.mp3 -c:v copy -c:a aac -strict experimental mvresult.mp4