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


Answers:


173

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

for i in *.avi;
  do name=`echo "$i" | cut -d'.' -f1`
  echo "$name"
  ffmpeg -i "$i" "${name}.mov"
done

24
如果您像我一样,并且文件名中有很多空格(以及一些其他有问题的字符),则建议添加双引号:ffmpeg -i“ $ i”“ $ name.mov”;
Pif 2012年

7
我遇到了错误i was unexpected at this time.
Keavon 2014年

5
do name=`echo "${i%.*}"`;将对其中带有点(和空格)的文件名起作用。
Nepoxx

8
哇,这个答案太复杂了。请参阅单行答案之一。
foob​​arbecue

2
.batWindows 支持吗?
Jazuly

289

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

for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done

1
这太完美了,谢谢!这是一条完整的命令,最终对我很有用:对于* .avi中的我;做ffmpeg -i“ $ i” -c:a aac -b:a 128k -c:v libx264 -crf 20“ $ {i%.avi} .mp4”; 完成
Phil Kulak

1
@Junaid 1)确保输出文件使用与输入不同的名称,或输出到另一个目录,因为ffmpeg不能输入和输出到同一文件。2)我不确定Bash命令是否可以在Windows 10本机上运行。也许我应该补充一点,它针对的是可以本地使用Bash的系统,例如Linux和macOS。lxs为该问题提供了Windows答案。
llogan

3
很棒的答案。也可以使用带空格的文件名!
wisbucky

1
这应该是最佳答案。诚然,为什么解释{$ i%。*}并不简单,但是如果您可以将其放在一边并“使用”,则可以快速进行修改以适应需要。例如,我转换数百的.mp4的的(与具有文件名空格和特殊字符),使用为更小的格式:对于i中的.mp4; 做ffmpeg -i“ $ i” -s 512x288 -c:复制“ $ {i%。 } .m4v”; 完成
托尼·M

1
如果要从H.265到H.264进行转码,这是一种常见的用例,那么如果希望将字符串“ x265”替换为“ x264”,则可以使用Bash参数替换for f in *.mkv; do ffmpeg -i "$f" -map 0 -movflags faststart -c:v libx264 -c:a copy -c:s copy "${f/x265/x264}"; done
特拉维斯·朗亚德

68

在Windows上:

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

19
如果在批处理(.bat)文件中运行此命令,则需要将%符号加倍=> %%
hB0 2015年

知道如何运行此命令,但是将其复制到包含原始文件元数据的新文件中吗?
Barryman9000 '16

@ Barryman9000这是很久以前了,但我认为您可以通过一个输出文件选项
lxs

@lxs感谢您的跟进。我最终通过将新文件的名称更改为原始文件的创建日期来使用Powershell进行了操作stackoverflow.com/a/35671099/197472
Barryman9000 '16

用它来删除元数据。但这给了我拒绝访问错误。因此,我更改了输出文件名,并为其留了额外的空间以使其成为新文件。FOR /F "tokens=*" %G IN ('dir /b *.mp3') DO ffmpeg -i "%G" -map_metadata -1 -c:v copy -c:a copy "%~nG .mp3"
Junaid

28

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

for i in *.avi; do ffmpeg -i "$i" -qscale 0 "$(basename "$i" .avi)".mov  ; done

.mov的默认编码器是libx264(如果可用),但是此编码器将忽略-qscale。将其删除并使用默认设置,或者改用默认设置-crf(默认为-crf 23)。
llogan

1
如果文件名中有空格,则该命令将失败,因为未加反引号的basename子shell。这正是bash改用shell扩展的原因:对于* .avi中的i;做ffmpeg -i“ $ i” -qscale 0“ $(基本名” $ i“ .avi)”。mov; 完成
Calimo

谢谢@ Calimo完全同意-我已经更新了我的答案
卵黄

22

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

find . -exec ffmpeg -i {} {}.mp3 \;

我将其与答案结合使用,以将VTT转换为SRT,以达到最佳效果。find -name "*.vtt" -exec ffmpeg -i {} {}.srt \;
凹槽复数

我执行以下命令,稍加修改即可将所有mp4转换为mp3:find *.mp4 -exec ffmpeg -i {} {}.mp3 \;
swdev

1
或者,如果您想转换多种文件类型:find . -name *.ogg -or -name *.wma -exec ffmpeg -i {} {}.mp3 \;
bonh

将所有wma文件转换为mp3,然后将其删除:find . -name *.wma -exec ffmpeg -i {} {}.mp3 \; -exec rm {} \;
Panagiotis

20

对于Windows:

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

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

for %i in (*.mp4) do ffmpeg -i "%i" "%~ni.mp3"

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


17

对于任何想用ffmpeg进行批量转换但又想拥有方便的Windows界面的人,我开发了此前端:

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

它为ffmpeg增添了一个窗口时尚界面,进度条和剩余时间信息,这些是我在使用ffmpeg时经常错过的功能。


好的,这是一个不错的项目!我一直在追赶我的尾巴一个小时,试图让ffmpeg接受Windows中的相对输出文件路径,这让它感觉像作弊。编辑:我用它来将.xwm转换为.flac
semtex41 '18

6

如果您使用的是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

要与其他格式进行转换,请更改'*.avi'.mp4根据需要进行更改。在大多数Linux发行版存储库中,GNU parallel在一个通常称为的软件包中列出parallel


您不能通过!在bash单线的末尾添加相同内容来做同样的事情吗?
stib

3

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

old_extension=$1
new_extension=$2

for i in *."$old_extension";
  do ffmpeg -i "$i" "${i%.*}.$new_extension";
done

它需要2个参数来使其更加灵活:

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

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

sh batch_convert.sh mkv mp4

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

如您所见,它更具通用性。只要ffmpeg可以转换它,就可以指定任何两个扩展名。


那就是最好的
安德烈亚斯·普朗

3

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

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

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


3

当然,PowerShell已经问世,它经过专门设计,可以使这种事情变得非常简单。

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

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

ls

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

然后,我们将这些内容过滤为仅要转换的文件类型-例如“ avi”。

ls | Where { $_.Extension -eq ".avi" }

之后,我们将通过将该信息传递给FFmpeg ForEach

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

$_.Name.Replace(".avi", ".mp3")

因此,让我们将所有这些放在一起,结果就是:

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

这将通过FFmpeg将所有“ .avi”文件转换为“ .mp3”文件,只需替换引号中的三项内容即可确定所需的转换类型,并可以在FFmpeg中随意添加任何其他参数ForEach

您可以更进一步,最后添加Remove-Item以自动删除旧文件。

如果ffmpeg不在您的路径中,并且实际上在您当前所在的目录中,请在该目录中./ffmpeg而不是ffmpeg

希望这对任何人有帮助。


1
PowerShell很棒,谢谢!万一其他人在运行此程序时遇到麻烦:请将此命令放在.ps1文件中,而不是.bat文件中。Set-ExecutionPolicy RemoteSigned如果您以前从未运行过PS脚本,则必须以管理员身份运行。
starpause

好吧,通常我只是想直接在PowerShell中运行它,所以我真的没有想到这一点!很好的提示!
ABPerson

2
for i in *.flac;
  do name=`echo "${i%.*}"`;
  echo $name;
  ffmpeg -i "${i}" -ab 320k -map_metadata 0 -id3v2_version 3 "${name}".mp3;
done

使用[1] [2]将文件批处理flacmp3(对于带空格的文件名来说是安全的)


2

视窗:

@echo off
for /r %%d in (*.wav) do (
    ffmpeg -i "%%~nd%%~xd" -codec:a libmp3lame -c:v copy -qscale:a 2 "%

%~nd.2.mp3"
)

这是质量2的可变比特率,您可以根据需要将其设置为0,但是除非您有一个非常好的扬声器系统,否则它就毫无价值


1

如果您希望图形界面使用ffmpegX进行批处理,请尝试使用Quick Batcher。它是免费的,将使用您最后的ffmpegX设置来转换您放入其中的文件。

请注意,您不能将文件夹拖放到Quick Batcher上。因此,选择文件,然后将其放入快速批处理程序。


2
“ Quick Batcher”软件仅适用于MAC OS
Mohammad ElNesr '17


0

这将从当前目录中的所有jpg文件创建mp4视频。

echo exec("ffmpeg -framerate 1/5 -i photo%d.jpg -r 25 -pix_fmt yuv420p output.mp4");

0

对于Windows,这不起作用

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

即使我加倍%

我什至建议:

-acodec ***libmp3lame***

也:

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

这是答案,还是试图发布新问题作为答案?在后一种情况下,请创建一个全新的问题,尽管可能会在此处链接以获取背景信息。
6

0

这就是我用来将AVI批量转换为1280x mp4的方式

FOR /F "tokens=*" %%G IN ('dir /b *.avi') DO "D:\Downloads\ffmpeg.exe" -hide_banner -i "%%G" -threads 8 -acodec mp3 -b:a 128k -ac 2 -strict -2 -c:v libx264 -crf 23 -filter:v "scale=1280:-2,unsharp=5:5:1.0:5:5:0.0" -sws_flags lanczos -b:v 1024k -profile:v main -preset medium -tune film -async 1 -vsync 1 "%%~nG.mp4"

作为cmd文件运行良好,运行它,循环在该文件夹中找到所有avi文件。

调用MY(为您更改)ffmpeg,传递输入名称,设置用于锐化后重新缩放。我的概率不需要CRF和-b:v 1024k“ ...”

输出文件是输入文件减去扩展名,mp4是新的扩展名。


0

我在linux中使用这种单行代码将文件(通常为H265)转换为可以在Kodi上播放的东西,而不会出现问题:

for f in *.mkv; do ffmpeg -i "$f" -c:v libx264 -crf 28 -c:a aac -b:a 128k output.mkv; mv -f output.mkv "$f"; done

这将转换为临时文件,然后替换原始文件,因此转换后的名称保持不变。


0

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

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

-1

小PHP脚本做到这一点:

#!/usr/bin/env php
<?php
declare(strict_types = 1);
if ($argc !== 2) {
    fprintf ( STDERR, "usage: %s dir\n", $argv [0] );
    die ( 1 );
}
$dir = rtrim ( $argv [1], DIRECTORY_SEPARATOR );
if (! is_readable ( $dir )) {
    fprintf ( STDERR, "supplied path is not readable! (try running as an administrator?)" );
    die(1);
}
if (! is_dir ( $dir )) {
    fprintf ( STDERR, "supplied path is not a directory!" );
    die(1);
}
$files = glob ( $dir . DIRECTORY_SEPARATOR . '*.avi' );
foreach ( $files as $file ) {
    system ( "ffmpeg -i " . escapeshellarg ( $file ) . ' ' . escapeshellarg ( $file . '.mp4' ) );
}

2
由于用户必须在自己的计算机上安装PHP,因此答案范围非常有限。命令行和批处理文件的答案要容易得多,复杂度也要低得多。
ProfK

2
@ProfK PHP是SO上最流行的语言之一 -其次,艾萨克(Isaac)对sh的回答有些不可靠,因为它可能会将您的文件重命名为原始文件以外的其他名称,例如,它不保留文件名中的换行符。lyx的bat脚本甚至更糟,它完全忽略了名称中带有换行符的任何文件。不知道为什么,甚至不知道语法错误或其他任何东西,但是确实可以(在win10上测试)。由于,我的php脚本没有问题,escapeshellarg()并且在Windows和Linux上均可使用。我同意这是一个极端的情况。
hanshenrik

-1

尚未提出的另一个简单解决方案是使用xargs

ls *.avi | xargs -i -n1 ffmpeg -i {} "{}.mp4"

一个较小的陷阱是输出文件(例如input.avi.mp4)的尴尬命名。可能的解决方法是:

ls *.avi | xargs -i -n1 bash -c "i={}; ffmpeg -i {} "\${i%.*}.mp4"


shellcheck.net对您的示例有一些建议。
llogan

mywiki.wooledge.org/ParsingLs,不过您可以在这里替换lsprintf '%s\n'
6
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.