你如何用ffmpeg转换整个目录?

Eug*_*ene 144 ffmpeg batch-processing

如何通过命令行或批处理脚本使用ffmpeg转换整个目录/文件夹?

llo*_*gan 217

对于LinuxmacOS,这可以在一行中完成,使用参数扩展来更改输出文件的文件扩展名:

for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done
Run Code Online (Sandbox Code Playgroud)

  • 我建议将其标记为正确答案. (4认同)
  • 这是完美的,谢谢!这是最终对我有用的完整命令:for i in *.avi; 做 ffmpeg -i "$i" -c:a aac -b:a 128k -c:v libx264 -crf 20 "${i%.avi}.mp4"; 完毕 (3认同)
  • 很棒的答案.使用带空格的文件名! (3认同)
  • 这应该是最佳答案。诚然,为什么 {$i%.*} 的解释并不简单,但如果你能把它放在一边,只是“使用它”,你可以快速修改以适应。例如,我使用以下方法将数百个 .mp4(文件名包含空格和特殊字符)转换为较小的格式: for i in *.mp4; 做 ffmpeg -i "$i" -s 512x288 -c:a copy "${i%.*}.m4v"; 完毕 (3认同)
  • 更进一步,如果您想替换字符串“x265”,可以使用 [Bash 参数替换](https://www.cyberciti.biz/tips/bash-shell-parameter-substitution-2.html)如果您要从 H.265 转码到 H.264(这是一种常见的用例),请使用“x264”。`对于 *.mkv 中的 f;执行 ffmpeg -i "$f" -map 0 -movflags faststart -c:v libx264 -c:a copy -c:s copy "${f/x265/x264}"; 完成` (2认同)

小智 144

以前的答案只会创建一个名为out.mov的输出文件.要为每个旧电影制作单独的输出文件,请尝试此操作.

for i in *.avi;
  do name=`echo "$i" | cut -d'.' -f1`
  echo "$name"
  ffmpeg -i "$i" "${name}.mov"
done
Run Code Online (Sandbox Code Playgroud)

  • 如果你像我一样,你的文件名中有很多空格(以及一些其他有问题的字符),我建议添加双引号:ffmpeg -i"$ i""$ name.mov"; (20认同)
  • 我收到的错误是"我此时出乎意料." (6认同)
  • 哇,这个答案令人难以置信的过于复杂.请参阅单行答案之一. (6认同)
  • ```do name =`echo"$ {i%.*}"`````将处理带有点(和空格)的文件名. (5认同)
  • 这是对 Windows 中的 `.bat` 的支持吗? (3认同)
  • @Jazuly 不,这是`sh` 语法。如果您还没有准备好完全放弃 Windows,您可以在 Windows 上安装 Bash。 (3认同)
  • 这对我来说似乎是在调整到第一个句号,而不是最后一个。因此文件名不相同,但末尾带有 .mov。 (2认同)

lxs*_*lxs 61

在Windows上:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"
Run Code Online (Sandbox Code Playgroud)

  • 如果在批处理(.bat)文件中运行此命令,则需要将%signs => %%加倍 (17认同)
  • 对于 **PowerShell**:`Get-ChildItem *.ogg -recurse | % { ffmpeg.exe -i $_.FullName -map_metadata -1 -c:v copy -c:a copy ("NewPath" + "\" +$_.Name) } ` 其中`NewPath` = 新目录路径。 (3认同)

yol*_*olk 24

单行bash脚本很容易做到 - *.avi用你的文件类型替换:

for i in *.avi; do ffmpeg -i "$i" -qscale 0 "$(basename "$i" .avi)".mov  ; done
Run Code Online (Sandbox Code Playgroud)

  • "*.avi"周围不应该有引号,这使得bash认为它是一个字符串而不是文件列表 (4认同)
  • 这个答案比标记的要好. (4认同)

use*_*001 16

要使用子目录进行转换,请使用eg

find . -exec ffmpeg -i {} {}.mp3 \;
Run Code Online (Sandbox Code Playgroud)

  • 或者,如果您想转换多种文件类型:`find . -name *.ogg -或 -name *.wma -exec ffmpeg -i {} {}.mp3 \;` (3认同)

Jan*_*hou 13

使用多个核心,这是最快的方法(使用并行):

parallel "ffmpeg -i {1} {1.}.mp4" ::: *.avi 
Run Code Online (Sandbox Code Playgroud)

  • @Luke,对于视频文件是的,但不是所有文件,例如声音文件(FLAC)或某些图像格式,您仍然可以通过使用并行来加速。 (3认同)

小智 12

@Linux 要转换一堆,我的一个班轮是这样的,例如(.avi 到 .mkv)在同一目录中:

for f in *.avi; do ffmpeg -i "${f}" "${f%%.*}.mkv"; done
Run Code Online (Sandbox Code Playgroud)

请注意输出语句中的双“%%”。它不仅为您提供第一个单词或输入文件名,还提供最后一个点之前的所有内容。


小智 11

对于任何想要使用ffmpeg批量转换任何内容但希望拥有方便的Windows界面的人,我开发了这个前端:

https://sourceforge.net/projects/ffmpeg-batch

它为ffmpeg添加了一个窗口时尚界面,进度条和剩余时间信息,这些功能在使用ffmpeg时总是错过.


小智 7

如果你有 GNU并行,你可以将下面的所有 .avi 文件并行转换vid_dir为 mp4,使用除了一个 CPU 内核之外的所有文件

find vid_dir -type f -name '*.avi' -not -empty -print0 |
    parallel -0 -j -1 ffmpeg -loglevel fatal -i {} {.}.mp4
Run Code Online (Sandbox Code Playgroud)

要从/转换为不同的格式,请根据需要更改'*.avi'.mp4。GNU 并行列在大多数 Linux 发行版的存储库中,通常称为parallel.


ABP*_*son 7

当然,现在 PowerShell 出现了,专门设计用于使类似的事情变得非常容易。

而且,是的,PowerShell也可用于 Windows 以外的其他操作系统,但它已预装在 Windows 上,因此这对每个人都应该有用。

首先,您需要列出当前目录中的所有文件,因此,我们将从以下内容开始:

ls
Run Code Online (Sandbox Code Playgroud)

ls -Recurse如果您也想递归转换子目录中的所有文件,也可以使用。

然后,我们会将这些过滤到我们想要转换的文件类型——例如“avi”。

ls | Where { $_.Extension -eq ".avi" }
Run Code Online (Sandbox Code Playgroud)

之后,我们将通过ForEach.

对于 FFmpeg 的输入,我们将使用FullName- 这是文件的完整路径。对于 FFmpeg 的输出,我们将使用Name- 但.avi末尾的替换.mp3。所以,它看起来像这样:

$_.Name.Replace(".avi", ".mp3")
Run Code Online (Sandbox Code Playgroud)

所以,让我们把所有这些放在一起,这就是结果:

ls | Where { $_.Extension -eq ".avi" } | ForEach { ffmpeg -i $_.FullName $_.Name.Replace(".avi", ".mp3") }
Run Code Online (Sandbox Code Playgroud)

这将通过 FFmpeg 将所有“.avi”文件转换为“.mp3”文件,只需替换引号中的三项即可决定您想要哪种类型的转换,并随意在ForEach.

您可以更进一步并添加Remove-Item到末尾以自动删除旧文件。

如果ffmpeg不在您的路径中,并且它实际上在您当前所在的目录中,请在./ffmpeg那里写入而不仅仅是ffmpeg.

希望这可以帮助任何人。

  • PowerShell 很棒,谢谢!如果其他人在运行此命令时遇到问题:将此命令放入“.ps1”文件中,而不是“.bat”文件中。如果您以前从未运行过 PS 脚本,则必须以管理员身份运行“Set-ExecutionPolicy RemoteSigned”。 (2认同)

Mar*_*ein 7

以下脚本在 Windows 上的 Bash 中运行良好(因此它在 Linux 和 Mac 上也应该同样运行)。它解决了我在使用其他解决方案时遇到的一些问题:

  • 处理子文件夹中的文件
  • 将源扩展替换为目标扩展,而不是仅仅附加它
  • 适用于名称中包含多个空格和多个点的文件(有关详细信息,请参阅此答案。)
  • 目标文件存在时可以运行,覆盖前提示

ffmpeg-batch-convert.sh:

sourceExtension=$1 # e.g. "mp3"
targetExtension=$2 # e.g. "wav"
IFS=$'\n'; set -f
for sourceFile in $(find . -iname "*.$sourceExtension")
do
    targetFile="${sourceFile%.*}.$targetExtension"
    ffmpeg -i "$sourceFile" "$targetFile"
done
unset IFS; set +f
Run Code Online (Sandbox Code Playgroud)

调用示例:

$ sh ffmpeg-batch-convert.sh mp3 wav

作为奖励,如果您想删除源文件,您可以像这样修改脚本:

sourceExtension=$1 # e.g. "mp3"
targetExtension=$2 # e.g. "wav"
deleteSourceFile=$3 # "delete" or omitted
IFS=$'\n'; set -f
for sourceFile in $(find . -iname "*.$sourceExtension")
do
    targetFile="${sourceFile%.*}.$targetExtension"
    ffmpeg -i "$sourceFile" "$targetFile"
    if [ "$deleteSourceFile" == "delete" ]; then
        if [ -f "$targetFile" ]; then
            rm "$sourceFile"
        fi
    fi
done
unset IFS; set +f
Run Code Online (Sandbox Code Playgroud)

调用示例:

$ sh ffmpeg-batch-convert.sh mp3 wav delete


Ale*_*una 6

我知道这可能是多余的,但我使用这个脚本来批量转换文件。

old_extension=$1
new_extension=$2

for i in *."$old_extension";
  do ffmpeg -i "$i" "${i%.*}.$new_extension";
done
Run Code Online (Sandbox Code Playgroud)

它需要 2 个参数才能使其更灵活:

  1. 您要转换的扩展名
  2. 您要转换为的新扩展名

我为它创建了一个别名,但您也可以像这样手动使用它:

sh batch_convert.sh mkv mp4
Run Code Online (Sandbox Code Playgroud)

这会将所有mkv文件转换为mp4文件。

正如你所看到的,它的用途更广一些。只要ffmpeg能转换就可以指定任意两个扩展名。


shu*_*238 6

对于Windows:

在这里,我将所有(.mp4)文件转换为(.mp3)文件。
只需打开cmd,转到所需的文件夹并键入命令。

快捷方式:(可选)
1.转到存在(.mp4)文件的文件夹
2.按住Shift并单击鼠标左键,然后选择“此处打开PowerShell窗口”
或“ 此处打开命令提示符窗口”
3.键入“ cmd” [注意:如果直接打开cmd而不是PowerShell,则跳过此步骤]
4.运行命令

for %i in (*.mp4) do ffmpeg -i "%i" "%~ni.mp3"
Run Code Online (Sandbox Code Playgroud)

如果要将其放入Windows 10上的批处理文件中,则需要使用%% i。

  • 事实上这个命令确实有效,但不要使用 powershell。 (5认同)
  • 这对我来说适用于命令提示符,但不适用于 powershell 在关键字 'for' 之后缺少打开 '('。 + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + ExcellentQualifiedErrorId : MissingOpenParenthesisAfterKeyword (2认同)

sti*_*tib 5

这里有点像代码高尔夫,但由于到目前为止几乎所有答案都是 bash(除了一个孤独的 cmd ),这里有一个使用 powershell 的Windows 跨平台命令(因为太棒了):

ls *.avi|%{ ffmpeg -i $_ <ffmpeg options here> $_.name.replace($_.extension, ".mp4")}
Run Code Online (Sandbox Code Playgroud)

您可以将 *.avi 更改为与您的源素材相匹配的任何内容。


小智 5

另外,如果您想在子文件夹中进行相同的转换。这是递归代码。

for /R "folder_path" %%f in (*.mov,*.mxf,*.mkv,*.webm) do (
    ffmpeg.exe -i "%%~f" "%%~f.mp4"
    )
Run Code Online (Sandbox Code Playgroud)


Tek*_*ist 5

我用它来为 Windows 上的电视节目或电影添加字幕。

只需在视频和子目录中创建“subbed”文件夹和bat文件。将代码放入bat文件中并运行。

for /R  %%f in (*.mov,*.mxf,*.mkv,*.webm) do (
    ffmpeg.exe  -i "%%~f" -i "%%~nf.srt" -map 0:v -map 0:a -map 1:s -metadata:s:a language=eng -metadata:s:s:1 language=tur -c copy ./subbed/"%%~nf.mkv"
    )
Run Code Online (Sandbox Code Playgroud)