-->

如何使用PowerShell和BASH为FFmpeg编写脚本

文章特色图片

FFmpeg被设计为视频和音频录制的跨平台解决方案, 转换, 和流媒体. 它的“关于”页面将命令行工具描述为“领先的多媒体框架”, 能够解码, 编码, 码, mux, 多路分配器, 流, 过滤和播放人类和机器创造的几乎所有东西.能够在Linux, Mac OS X, Windows和一系列其他构建环境上运行,FFmpeg 5.1.2可在此下载 ffmpeg.org. 你可以找到 介绍FFmpeg编码和可下载的脚本在这里.

大多数FFmpeg用户首先创建一个简单的静态命令行, 经过多次调试, 对于单个输入文件和选定的编码参数工作得很好. 试图在不同的文件或参数中重用该命令行通常是一种容易出错的搜索体验, 复制, 然后粘贴,然后冲洗,重复以纠正任何错误.

在命令字符串中使用变量和“for循环”简化了现有脚本的重用,并有助于自动化它们的操作. 虽然你不能在Windows命令窗口中使用这些脚本, 你可以在Windows上使用微软PowerShell,在Linux和Mac上使用Bash. 在本教程中,您将学习如何使用PowerShell和Bash创建和运行这样的脚本.

具体来说,你将学习如何像这样转换命令字符串:

输入.mp4 -c:v libx264 -vf scale=-1:1080 3 m - b: v -maxrate 6M -bufsize 6M -g 48预置超快输出.mp4

中所示的脚本 图1(下面).

script2-variables.sh

图1. 这个简单的Bash脚本产生与上面的命令字符串相同的输出. 这是script2-variables.Sh,您可以下载 在这里

使用新脚本, 所有可调参数都在上面, 简化测试和生产的修改. 您还将了解如何将此脚本应用于文件夹中的多个文件,以及如何使用源文件和所选变量自定义文件名. 最后, 我将向您展示如何将输出文件存储在一个单独的自定义文件夹中——所有这些都适用于Bash和PowerShell. 对于本文, 我假设您了解Windows Command窗口的FFmpeg编程的基础知识, 但不熟悉Bash或PowerShell.

您可以下载所有脚本 在这里. 请解压缩文件, keeping all folders intact; later scripts look for input files in folders other than w在这里 the script is located. 我放了一段10秒的 Sintel 来简化本文中的示例工作. 非常感谢搅拌机基金会优雅地创建这个剪辑,并允许它被用于这样的目的.

什么是Bash和PowerShell?

根据 GNU.orgBash是GNU操作系统的shell或命令语言解释器. 这个名字是“伯恩再次壳”的首字母缩略词。, 对斯蒂芬·伯恩的双关语, 当前Unix shell sh的直接祖先的作者, 它出现在Unix的第七版贝尔实验室研究版本中.根据微软的说法, PowerShell是“一个由命令行shell组成的跨平台任务自动化解决方案”, 脚本语言, 以及配置管理框架.”

如果您熟悉Windows命令窗口, 这两个shell都是更强大的命令窗口. Bash是在Ubuntu上按ctrl - alt - t或在Mac上运行terminal时打开的终端. 在Windows搜索栏中输入“Powershell”,Windows Powershell窗口就会以蓝色显示. 两种体系都有各自的特点. 如果您签入Bash脚本 图1,您将看到字符串#!/bin/bash在顶部. 这是必需的Shebang,它告诉Ubuntu使用哪个解释器来执行脚本. Bash脚本通常与 .Sh扩展,这是这里遵循的惯例. PowerShell脚本不需要Shebang,使用 .PS1扩展,它允许您在Windows百家乐软件管理器中像批处理文件一样运行它. 这里使用和包含的所有PowerShell脚本都使用 .PS1扩展.

脚本运行权限

与Command窗口不同,您必须询问每个shell的权限才能运行脚本. 对于Bash,第一次运行类似S1-minimal的脚本.Sh在会话中,您可以通过以下命令请求执行脚本的权限:

chmod +x S1-minimal.sh

然后用下面的命令运行脚本:

./ S1-minimal.sh

您可以看到插入的两个命令 图2(下面) 在终端窗口. 郑重声明, 该脚本只包含前面所示的FFmpeg命令字符串, 实际上,我们将在本文中对“before”命令进行转换.

Bash

图2. Bash——请求运行第一个脚本的权限,然后运行它

如果您编辑和更新脚本, you don’t need to re-request the authority to execute it; it should just run. 在PowerShell中,你必须使用以下命令请求权限来运行任何脚本:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

这包括在该会话期间运行的所有脚本,但是您必须在每个会话中重复它. 然后使用以下命令运行脚本:

.\ S1-minimal.ps1

注意,Bash中使用的是反斜杠而不是正斜杠. 另外, 您可以在百家乐软件管理器中右键单击脚本并选择“使用PowerShell运行”(下面的图3).

PowerShell

图3. PowerShell——请求运行所有脚本,然后运行第一个脚本

您现在可以运行其中一个脚本,也可以同时运行两个脚本. 显然,您需要在系统上安装FFmpeg. 两个脚本都应该创建一个名为output的文件 .Mp4在同一文件夹的脚本和源文件.

在Bash中部署变量

变量是一种用描述性名称标记数据,然后稍后在脚本中引用它的机制. 它们在Bash和PowerShell中的功能相同,尽管操作略有不同. 图4(下面) 等于 图1 并展示了一个Bash脚本,它使用变量来运行本文开头所示的相同的FFmpeg命令字符串.

Bash脚本

图4. 一个简单的Bash脚本(s2 -变量).sh)

以下是与变量相关的Bash规则:

  • 使用字母数字名称定义变量(如 高度).
  • 将一个值赋给不带空格的等号(=)变量.
  • 如果变量是一个文本字符串,用引号(比特率=“3 m”).
  • 如果变量是整数,不要使用引号(身高= 1080).
  • 通过前面带美元符号的变量名在脚本中引用该变量. 所以,不是b: v 3 m,它是——b: v $比特率.

注意,第10-12行末尾的反斜杠是行延续字符,它告诉Bash不要在这些行之间插入换行字符. 这使您可以将命令字符串分解为易于创建和调试的可读行. 如果您将脚本分成这些可读的行,但不使用行延续字符, 您的文本编辑器将插入不可见的换行字符,这些字符将中断脚本操作.

说到换行, 如果您在不同于运行脚本的操作系统上创建脚本, 确保为目标操作系统保存脚本. 你可以在底部的中间看到这个 图4. 虽然我在Windows上运行notepad++,但我为UNIX操作系统保存了脚本. 如果您忘记这样做,请将脚本保存为Windows格式, 脚本看起来会很完美, 但是当你试图运行它时,你会得到虚假的错误.

现在是运行script2-variables的好时机.sh. 这应该会生成一个非常相似的文件, 如果不完全相同, 到使用第一个脚本创建的文件.

接下来,我们将看看变量是如何为PowerShell工作的.

在PowerShell中部署变量

图5(下面) 显示了PowerShell的相同脚本.

的S2-variables.ps1脚本在PowerShell (s2 -变量.ps1)

图5. 的S2-variables.ps1脚本在PowerShell (s2 -变量.ps1)

下面是在PowerShell中创建和部署变量的等价规则.

  • 定义一个变量,它的名称由字母数字组成,前面有一个美元符号(美元的高度).
  • 将一个值赋给带有等号(=)的变量,中间没有空格.
  • 如果变量是一个文本字符串,用引号($bitrate = "3M").
  • 如果变量是整数,则不需要引号(美元的高度 = 1080).
  • 通过前面带美元符号的变量名在脚本中引用该变量. 所以,与其 3 m - b: v,它是 - b: v $比特率.

在PowerShell, 行延续字符是一个反勾号(键盘左上角Tab键上方的键). 如果您将脚本分成多行以方便阅读, 确保将它们插入所有脚本行的最后一个字符,直到最后一行.

尝试运行script2-variables.Ps1与您的短1080p30输入文件. FFmpeg应该会生成一个非常相似的文件, 如果不完全相同, 到script1-minimal生成的文件.ps1.

在Bash中自定义输出文件名和文件夹

无论是测试还是生产, 您经常希望创建描述性文件名,以详细说明文件的编码方式. 例如,在测试预设时,您可能希望文件名中包含_ultrafast. 对于生产,您可能需要分辨率和比特率. 让我们探索一下如何在Bash中实现这一点(下面的图6)和PowerShell.

Bash——自定义输出文件名和输出路径

图6. Bash——自定义输出文件名和输出路径

的 top variables section is identical; 在这里’s an explanation of the new code under the comment #folders and filenames and w在这里 it impacts the updated script (S3-filenames.sh):

  • 输入= "./ / sintel来源.mp4" 创建一个名为input的新变量,用于标识文件名和文件夹. 我们在命令字符串中使用这个新变量,而不是输入文件的名称和位置. 我们将在下一课中详细介绍这个输入变量.
  • 基础= $ (basename ${输入%.*})创建一个名为base的新变量,以便在命名输出文件夹和输出文件时使用.
  • basename命令获取没有任何路径信息的输入文件名.
  • ${输入%.*} 从输出文件和输出文件夹中的基名中删除文件扩展名.
  • $() 包装表达式以执行它,并在运行脚本时将其输出存储在基本变量中.
  • outputfolder = ".美元/输出/基地” 创建另一个变量,该变量将输出文件夹设置为目标文件夹,并将基本变量设置为子文件夹.
  • Mkdir -p "$outputfolder" 在输出文件夹变量中创建尚不存在的任何文件夹和子文件夹.
  • 输出= " $ {outputfolder} /{基地}_{高度}美元p _{比特率}_{预设}美元.mp4" 创建输出文件名和存储位置. 文件名可以由任何变量和静态文本(如后面的p)组成 ${高度}). 这个变量被替换到命令行中作为输出文件名.
  • FFmpeg脚本是相同的,除了变量input和output被替换为在前一个脚本中直接指定的输入和输出文件.

当您运行此脚本时,sinintel.mp4必须在脚本源文件夹的源子文件夹中,大概是Lesson_3. 运行脚本之后, 您将看到一个带有sinintel子文件夹的输出文件夹和名为sintel_1080p_3M _ultrafast的输出文件.mp4. 你可以在里面看到文件 图7(下面),其文件夹结构位于文件bin的上方行. So, 您将编码的文件组织到一个不同的子文件夹中,并使用所需的变量和文本命名该文件.

s3 - filename脚本生成了如下所示的文件夹结构和输出文件

图7. s3 - filename脚本生成了如下所示的文件夹结构和输出文件

自定义输出文件名和文件夹在PowerShell

现在,让我们对带有s3文件名的PowerShell进行相同的分析.ps1脚本如图8所示.

PowerShell——自定义输出文件名和输出路径

图8. PowerShell——自定义输出文件名和输出路径

的 top variables section is identical; 在这里’s the new code under the comment #folders and filenames and w在这里 it impacts the updated script.

  • $input = ".\ \输入来源.mp4" 创建一个名为input的新变量,用于标识文件名和文件夹. 我们在命令字符串中使用它,而不是输入文件的名称和位置. 在下一节中,我们将详细介绍这个输入变量.
  • $base = (Get-Item "${input}")).Basename将输入文件的基名的值赋给变量" $base ". 具体地说,该脚本使用Get-Item cmdlet在属性指定的路径上检索项 “输入美元” 变量,然后使用 .Basename 属性检索文件的基本名称.
  • 美元outputfolder = ".\ \输出美元基地” 创建另一个变量,该变量将输出文件夹设置为目标文件夹,将基文件夹设置为子文件夹.
  • New-Item -type目录-path $output文件夹 在outputfolder变量中创建尚不存在的任何文件夹和子文件夹.
  • 输出美元= " $ {outputfolder} \ p{基地}_{高度}美元_{比特率}_{预设}美元.mp4" 创建输出文件名和存储位置. 的
    文件名可以包含任何变量和静态文本(如${高度}后面的p). 这个变量被替换到命令行中作为输出文件名.
  • 与Bash脚本一样, FFmpeg脚本是相同的,除了变量input和output被替换为在前一个脚本中直接指定的输入和输出文件.

与Bash脚本一样,sinintel.mp4必须在Lesson_3的sources子文件夹中. 运行脚本之后, 您将看到一个带有sinintel子文件夹的输出文件夹和名为sinintel _ 1080p_ 3M _ ultrafast的输出文件.mp4.

在Bash中对文件夹中的多个文件进行编码

最后两节将教您如何使用Bash中的for循环和PowerShell中的for each命令对文件夹中的多个文件进行编码. 为了节省屏幕截图的大小, 我将排除可下载脚本中未更改且可用的最重要变量. 注意,对于这个练习,源文件夹有三个Sintel1 (Sintel1)的副本.mp4、Sintel2.mp4和Sintel3.mp4).

图9(下面) 显示了S4-filelist中的相关部分.sh. 该脚本的大部分内容与前一个脚本相同, 包括基地, 输出文件夹, 输出文件名.

在Bash中执行for循环

图9. 在Bash中执行for循环

新的是第14行的for循环. 从操作上讲,这需要做些什么:

  • inputfolder = "./来源” 将输入文件夹标识为源.
  • = (ls inputfolder美元/ *文件.mp4) 告诉Bash以MP4扩展名列出输入文件夹中的所有文件. 这是脚本将处理的三个sinl文件.
  • 周围是 $() 使Bash执行该命令并将其输出存储到定义为的数组变量中 ${文件[@]}.
  • 然后Bash通过图9中输出行下面的FFmpeg命令运行文件列表中的每个输入文件, 对每个文件进行编码
    将其放入相应的输出文件夹中.

运行这个脚本之后, 您将看到输出文件夹,每个输入文件有三个独立的子文件夹(下面的图10). 每个子文件夹将包含一个输出文件,源名称后面跟着_ 1080p _ 3M _ ultrafast.mp4.

S4-filelist.Sh将为每个源文件创建输出文件夹,并将编码后的文件存储在该文件夹中.

图10. S4-filelist.Sh将为每个源文件创建输出文件夹,并将编码后的文件存储在该文件夹中.

编码多个文件在一个文件夹在PowerShell

现在让我们使用如下所示的脚本在PowerShell中执行相同的操作 图11(下面).

通过FFmpeg命令脚本运行源文件夹中的所有MP4文件

图11. S4-filelist.Sh将为每个源文件创建输出文件夹,并将编码后的文件存储在该文件夹中.

同样,剧本的大部分内容没有改变. 以下是关键因素.

  • 美元的文件 = Get-ChildItem-Path ".“过滤器* \来源.mp4 使用Get-ChildItemcmdlet获取“sources”文件夹中的所有mp4文件,并将列表存储在美元的文件变量中.
  • foreach ($ files中的$file)告诉PowerShell对目录中的所有文件应用FFmpeg命令脚本 美元的文件 变量,这是脚本将处理的三个sinl文件.
  • PowerShell然后通过输出行下面的FFmpeg命令运行文件列表中的每个输入文件 图11,对每个文件进行编码,并将其放入自己的输出文件夹中.

运行脚本时, 您应该看到三个输出文件夹, 每个都有经过编码和适当命名的文件. 如果您将一堆其他MP4文件转储到源文件夹中,脚本也会对这些文件进行编码.

在这里的描述和示例脚本之间, 您应该能够将这些技术应用于一系列编解码器和编码任务.

作者要感谢 法布尔Lambeau 感谢他对这本书的重大技术贡献.

流媒体覆盖
免费的
合资格订户
现在就订阅 最新一期 过去的问题
相关文章

如何用FFmpeg制作VVC

任何时候你开始使用新的编解码器, 为了实现最佳性能/质量优化,您应该运行一些基本测试. 在本文中, 我将带您完成这些测试,同时使用包含Fraunhofer VVC编解码器的FFmpeg版本编码VVC.

参加流媒体东部的5大理由

1月时将主持研讨会, 演讲, 以及涵盖高级编解码器的面板, 用于远程制作的设备, WebRTC, 低延时。, 并于5月23日至25日在波士顿的流媒体东部上降低带宽和存储成本.

网络广播、视频会议和FFmpeg在流媒体东部的聚光灯下

Robert Reinhardt的研讨会将涵盖使用FFmpeg和管理视频会议输入和输出的最新提示和技巧, 而演示和小组讨论将着眼于将您的网络广播和事件流媒体工作提升到一个新的水平.

如何编码与FFmpeg 5.0

而不是专注于随机的任务, 本教程将带您了解使用最新版本的FFmpeg进行编码的基础知识.

莫斯科国家报告:俄罗斯仍是普京的首选.264,但对HEVC和AV1有影响

好消息是:一如既往,莫斯科国立大学的编解码器研究是最全面的. 坏消息是:除非你是TikTok或腾讯,否则你无法访问一些表现最好的应用.

发现你不能没有的六个FFmpeg命令

任何进行性能或基准测试的人, 请看一下:本文中的六个命令可以帮助处理在任何工作室或编码工具中出现的基本任务.

如何自动化FFmpeg和Bento4与Bash脚本

只有一些初学者级别的脚本, 您可以使用开源工具将多个字段编码和打包为HLS和DASH输出.

开始测试的时间:FFmpeg第4轮.0和增加AV1支持

AV1提供与HEVC相同的质量,但数据速率较低. 但就目前而言,进展缓慢. 一段5秒的视频编码耗时23小时46分钟.

提及的公司及供应商