Bash 脚本:自动为 mpeg-dash 进行 ffmpeg 编码

2024-05-21

我正在编写一个 bash 文件来创建视频编码和串联,以供 dash 实时流媒体使用, 基本上,它读取输入视频文件夹,将所有视频编码为三种分辨率格式,然后将它们连接起来创建三个适应集。

DIAGRAM:

该脚本检查 fps 一致性,

如果输入不是 1920 x 1080p,则强制/缩放分辨率,

插入频道标志png,

剪切所有视频输入的末尾,以使它们以闭合 gop 结束,这可以确保不存在具有不同长度的音频和视频轨道的视频。

ISSUE:

实际上,我不确定串联过程是否尊重编码后的闭合 GOP 对齐。 我还尝试剪切串联结果的末尾,以便使其在封闭的 gop 上也没有小数点地完成,但我无法擦除总持续时间中的所有小数点:

total duration in seconds: 826.795000
total duration corrected in seconds: 826

但ffprobe测得的真实持续时间是

824.044000

我尝试检查关键帧与 mp4box 的对齐情况,他们是否教过但没有任何结果:

MP4Box -info TRACK_ID source1.mp4 2>&1 | grep GOP

这是我第一次使用“视频脚本”,可能我不知道要为 TRACK_ID 提供什么输入

重击脚本:

#!/bin/bash
#CANCAT 0.2

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

    _t=$(ffprobe -i "$f" -show_entries format=duration -v quiet -of csv="p=0")
    times+=("$_t")

    _f=$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \\(.*\\) fp.*/\\1/p")
    fps+=("$_f")
done
#SUM ALL DURATIONS
TOTALDURATION=$( echo "${times[@]}" | sed 's/ /+/g' | bc )
#DELETE DECIMAL
DURROUND=$(echo "$TOTALDURATION" | cut -d'.' -f1) 
#GET REST OF DIVISION BY 2 AS GOP
TOTDELTA="$((DURROUND%2))"
#SUBTRACT DELTA FROM TOTAL DURATION
TOTDUR="$(($DURROUND-$TOTDELTA))"

#GET NUMBER OF ELEMENTS IN FPS ARRAY  
tLen=${#fps[@]}
#CHECK FPS EQUALITY     
for tLen in "${fps[@]:1}"; do
    if [[ $tLen != ${fps[0]} ]]; then
        printf "WARNING: VIDEO’S FRAME-RATE 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
#GET DURATION OF EACH VIDEO
DUR="$(ffprobe -i "$f" -show_entries format=duration -v quiet -of csv="p=0")"
DUR=$(echo "$DUR" | cut -d'.' -f1) # DELETE DECIMAL
#GET FPS OF EACH VIDEO
FPS="$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p")"
#ROUND FPS OF EACH VIDEO
FPSC=$( echo "($FPS+0.5)/1" | bc )
#REMOVE EXTENSION FROM VIDEO FILE NAME
NAME=$(echo "$f" | cut -d'.' -f1)

#GET GOP
GOP="$((FPSC*2))"
DELTADUR="$((DUR%2))"
DUR="$(($DUR-$DELTADUR))"

#ENCODE 1080p
ffmpeg -y -i "$f" -i ../logo/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 -crf 22 -t $DUR -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10,scale=1920:1080,setsar=1" ../buffer/${NAME}-1080.mp4

#ENCODE 720p
ffmpeg -y -i ../buffer/${NAME}-1080.mp4 -c:a aac -b:a 256k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts keyint=$GOP:min-keyint=$GOP:no-scenecut -bf 0 -s 1280x720 -r $FPSC -b:v 2400k -maxrate 2400k -bufsize 1500k -profile:v main -crf 22 -t $DUR ../buffer/${NAME}-720.mp4

#ENCODE 360p
ffmpeg -y -i ../buffer/${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 -crf 22 -t $DUR ../buffer/${NAME}-360.mp4
done


#enter in buffer
cd ..
cd buffer

#CONCAT 1080 SET
# with a bash for loop
for f in ./*1080.mp4; do echo "file '$f'" >> 1080list.txt; done

ffmpeg -f concat -safe 0 -i 1080list.txt -t $TOTDUR -c copy ../output/1080set.mp4

#CONCAT 720 SET
# with a bash for loop
for f in ./*720.mp4; do echo "file '$f'" >> 720list.txt; done

ffmpeg -f concat -safe 0 -i 720list.txt -t $TOTDUR -c copy ../output/720set.mp4

#CONCAT 360 SET
# with a bash for loop
for f in ./*360.mp4; do echo "file '$f'" >> 360list.txt; done

ffmpeg -f concat -safe 0 -i 360list.txt -t $TOTDUR -c copy ../output/360set.mp4

#CLEAN BUFFER
rm *.mp4
rm *.txt

echo "CONCAT COMPLETED:"
echo "frame-rate: $fps"
echo "total duration in seconds: $TOTALDURATION"
echo "total duration corrected in seconds: $TOTDUR"

带有相关文件夹的完整文件:

带有文件夹的 BASH 脚本 https://www.sendspace.com/file/fe57fv

结果视频 https://www.sendspace.com/file/wkv5h1

有人可以帮助我理解为什么我无法消除 concat 期间总持续时间的小数部分? 以及如何检查整体关键帧对齐情况? 也欢迎我忽略的任何改进!

多谢!

Massimo


我知道算法中有一个很大的错误:总持续时间是在单个视频剪切过程之前计算的,因此总持续时间总是比有效串联持续时间更长,我修复了它,

now

total duration in seconds: 824.044000
total duration corrected in seconds: 824

ffprobe 测量:824.012000,我无法在没有小数的情况下得到它并检查整体关键帧对齐。

#!/bin/bash
#CANCAT 0.2

cd input
fps=()
# GET FPS OF ALL VIDEOS INTO ARRAY
for f in *.mp4; do

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

#GET NUMBER OF ELEMENTS IN FPS ARRAY  
tLen=${#fps[@]}
#CHECK FPS EQUALITY     
for tLen in "${fps[@]:1}"; do
    if [[ $tLen != ${fps[0]} ]]; then
        printf "WARNING: VIDEO’S FRAME-RATE 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
#GET DURATION OF EACH VIDEO
DUR="$(ffprobe -i "$f" -show_entries format=duration -v quiet -of csv="p=0")"
DUR=$(echo "$DUR" | cut -d'.' -f1) # DELETE DECIMAL
#GET FPS OF EACH VIDEO
FPS="$(ffmpeg -i "$f" 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p")"
#ROUND FPS OF EACH VIDEO
FPSC=$( echo "($FPS+0.5)/1" | bc )
#REMOVE EXTENSION FROM VIDEO FILE NAME
NAME=$(echo "$f" | cut -d'.' -f1)

#GET GOP
GOP="$((FPSC*2))"
DELTADUR="$((DUR%2))"
DUR="$(($DUR-$DELTADUR))"

#ENCODE 1080p
ffmpeg -y -i "$f" -i ../logo/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 -crf 22 -t $DUR -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10,scale=1920:1080,setsar=1" ../buffer/${NAME}-1080.mp4

#ENCODE 720p
ffmpeg -y -i ../buffer/${NAME}-1080.mp4 -c:a aac -b:a 256k -ar 48000 -ac 2 -async 1 -c:v libx264 -x264opts keyint=$GOP:min-keyint=$GOP:no-scenecut -bf 0 -s 1280x720 -r $FPSC -b:v 2400k -maxrate 2400k -bufsize 1500k -profile:v main -crf 22 -t $DUR ../buffer/${NAME}-720.mp4

#ENCODE 360p
ffmpeg -y -i ../buffer/${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 -crf 22 -t $DUR ../buffer/${NAME}-360.mp4
done


#enter in buffer
cd ..
cd buffer
times=()
for f in *1080.mp4; do
    _t=$(ffprobe -i "$f" -show_entries format=duration -v quiet -of csv="p=0")
    times+=("$_t")
done
#SUM ALL DURATIONS
TOTALDURATION=$( echo "${times[@]}" | sed 's/ /+/g' | bc )
#DELETE DECIMAL
DURROUND=$(echo "$TOTALDURATION" | cut -d'.' -f1) 
#GET REST OF DIVISION BY 2 AS GOP
TOTDELTA="$((DURROUND%2))"
#SUBTRACT DELTA FROM TOTAL DURATION
TOTDUR="$(($DURROUND-$TOTDELTA))"


#CONCAT 1080 SET
# with a bash for loop
for f in ./*1080.mp4; do echo "file '$f'" >> 1080list.txt; done

ffmpeg -f concat -safe 0 -i 1080list.txt -t $TOTDUR -c copy ../output/1080set.mp4

#CONCAT 720 SET
# with a bash for loop
for f in ./*720.mp4; do echo "file '$f'" >> 720list.txt; done

ffmpeg -f concat -safe 0 -i 720list.txt -t $TOTDUR -c copy ../output/720set.mp4

#CONCAT 360 SET
# with a bash for loop
for f in ./*360.mp4; do echo "file '$f'" >> 360list.txt; done

ffmpeg -f concat -safe 0 -i 360list.txt -t $TOTDUR -c copy ../output/360set.mp4

#CLEAN BUFFER
rm *.mp4
rm *.txt

echo "CONCAT COMPLETED:"
echo "frame-rate: $fps"
echo "total duration in seconds: $TOTALDURATION"
echo "total duration corrected in seconds: $TOTDUR"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Bash 脚本:自动为 mpeg-dash 进行 ffmpeg 编码 的相关文章

随机推荐

  • 如何使用 Ansible 遍历嵌套的 dict 结构?

    我在 ansible 剧本中有以下 dict 结构变量 apache vhosts name foo server name foo com server aliases a foo com b foo com c foo com name
  • APNS(Apple 推送通知服务器)的反馈服务

    我们正在使用Java作为推送通知提供商APNS I我能够将消息发送到APNS但我不知道如何获得该消息的反馈 请帮忙 反馈服务具有类似于用于发送推送通知的接口的二进制接口 您可以通过以下方式访问生产反馈服务feedback push appl
  • 正则表达式可以与 C++ 中的字符数组一起使用吗

    我正在开发一个无法使用字符串库文件的程序 而是使用字符数组 我能够使用正则表达式 并且想知道是否有办法使用正则表达式和字符数组 甚至正则表达式和单个字符 我问的原因是当我尝试在匹配中使用我的 char 数组时 xUtility 会抛出一堆来
  • CSS Overflow 属性在 iPad 中不起作用

    我正在为 iPad 设计一些 html 页面 在尝试像 yscroll auto 这样的 css 溢出属性时 iPad 中没有出现滚动条 内容也没有滚动 我在 ipad 模拟器和设备中尝试过 有没有其他方法可以实现这个属性 请帮帮我 提前致
  • Google App Engine queue.yaml 无法在开发服务器中工作

    我无法让 dev appserver py 识别我使用queue yaml 创建的自定义队列 他们没有出现在http localhost 8000 taskqueue http localhost 8000 taskqueue 当我尝试向其
  • jQuery 中的 Javascript .files[0] 属性

    jQuery 中是否有与此语句等效的语句 var value document getElementById id files 0 使用附加 files 0 的标准 jQuery 选择器似乎不起作用 并且我找不到与 files 等效的 jQ
  • 无法读取序列化诊断文件:无效文件:无效诊断签名

    我收到这个奇怪的警告 我不确定是什么原因造成的 A dia https filext com file extension DIA文件扩展名据称表示核心有向图图形文件 我没有添加一个 该应用程序几乎没有用户界面 无法读取序列化诊断文件 错误
  • 如何使用键盘和鼠标控制相机 - Three.js

    我在 WEB GL 中有一个带有 Three js 的 3D 环境 并且我曾经使用 Orbitcontrols js http codepen io nireno pen cAoGI http codepen io nireno pen c
  • asp.net mvc 文件流结果

    问题的第一部分 我在数据库中有信息 我想从数据库获取它并将其另存为 txt文件给客户端 我已经用常规的 asp net 完成了它 但在mvc中还没有 我的信息不是图像 这些关于人民的信息 我看着这个网站 http www mikesdotn
  • Linux:如何设置进程的时区?

    我需要设置在 Linux 机器上启动的各个进程的时区 我尝试设置TZ变量 在本地上下文中 但它不起作用 有没有一种方法可以使用与系统日期不同的系统日期从命令行运行应用程序 这可能听起来很愚蠢 但我需要一种sandbox系统日期将被更改的地方
  • 在 C# 中引发事件[重复]

    这个问题在这里已经有答案了 我在微软练习测试中遇到了这个问题 我很困惑 这是问题 以下哪个 C 代码示例 是引发事件的正确方式 假设警报事件 AlarmEventArgs 类 以及 AlarmEventHandler 委托已 宣布 这是他们
  • 将 div 设置为 post 方法结果页面的目标容器

    我有一个 div 标签 也分为两个 div 这是代码 div div div div
  • Java HashMap 嵌套泛型与通配符

    我正在尝试创建包含自定义类的不同子类的哈希集的哈希映射值的哈希映射 如下所示 HashMap
  • 浏览器中缺少 Angular 12 源地图

    我们已经升级到角12最近遇到一个问题 即浏览器源映射丢失 因此我们无法调试我们的组件文件 因为没有任何组件文件 谁能建议我缺少什么 Angular 12 更改了默认的 ng build 以使用 生产 配置 你想要 sourceMap 所以尝
  • 如何在qt中创建正确的退出按钮

    我正在尝试创建一个退出按钮来正确关闭我在 QT 中制作的 GUI 我尝试通过以下方式执行此操作 include
  • Spring @Validated 在服务层

    Hej 我想使用 Validated group Foo class 在执行方法之前验证参数的注释 如下所示 public void doFoo Foo Validated groups Foo class foo 当我将此方法放入 Spr
  • 我应该把 .gitignore 放在哪里才能影响所有项目?

    我应该在哪里放置一个 gitignore文件以便我的所有项目都使用这些设置 我尝试了各种文件夹 只有将其放入项目文件夹中才能使其正常工作 但是设置 当然 仅应用于该项目 而不是我的其他项目 git 包含一个 全局 配置选项 可以告诉它在启动
  • FLAG_ACTIVITY_REORDER_TO_FRONT 被忽略

    我有一个包含项目列表的 FragmentActivity 当应用程序处于后台时 可以推送该项目列表 发生这种情况时 我想创建一个状态栏通知并提醒用户更新 当用户单击通知时 活动应重新排序到前面并显示在屏幕上 同时在列表底部显示新项目 所以我
  • 简单的WPF + MVVM绑定

    我有一个名为MyWindow源自于Window 我使用 MVVM 模式 因此在代码隐藏中我有以下字段 public MyViewModel ViewModel new MyViewModel ViewModel包含一个集合Person 我想
  • Bash 脚本:自动为 mpeg-dash 进行 ffmpeg 编码

    我正在编写一个 bash 文件来创建视频编码和串联 以供 dash 实时流媒体使用 基本上 它读取输入视频文件夹 将所有视频编码为三种分辨率格式 然后将它们连接起来创建三个适应集 DIAGRAM 该脚本检查 fps 一致性 如果输入不是 1