如何通过命令行或批处理脚本使用 ffmpeg 转换整个目录/文件夹?
31 回答
对于Linux和macOS ,这可以在一行中完成,使用参数扩展来更改输出文件的文件扩展名:
for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done
上一个答案只会创建 1 个名为 out.mov 的输出文件。要为每部旧电影制作单独的输出文件,请尝试此操作。
for i in *.avi;
do name=`echo "$i" | cut -d'.' -f1`
echo "$name"
ffmpeg -i "$i" "${name}.mov"
done
在 Windows 上:
FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"
对于 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。
单行 bash 脚本很容易实现 - 替换*.avi
为您的文件类型:
for i in *.avi; do ffmpeg -i "$i" -qscale 0 "$(basename "$i" .avi)".mov ; done
要使用子目录进行转换,请使用例如
find . -exec ffmpeg -i {} {}.mp3 \;
对于任何想用 ffmpeg 批量转换任何东西但又想拥有一个方便的 Windows 界面的人,我开发了这个前端:
https://sourceforge.net/projects/ffmpeg-batch
它为 ffmpeg 添加了一个窗口时尚界面、进度条和剩余时间信息,这是我在使用 ffmpeg 时总是错过的功能。
@Linux 要转换一堆,我的一个衬里是这样的,例如(.avi 到 .mkv)在同一目录中:
for f in *.avi; do ffmpeg -i "${f}" "${f%%.*}.mkv"; done
请注意输出语句中的双“%%”。它不仅为您提供第一个单词或输入文件名,还为您提供最后一个点之前的所有内容。
当然,现在 PowerShell 已经出现,专门设计用于使类似这样的事情变得非常容易。
而且,是的,PowerShell也可以在 Windows 以外的其他操作系统上使用,但它预装在 Windows 上,所以这应该对每个人都有用。
首先,您需要列出当前目录中的所有文件,因此,我们将从以下内容开始:
ls
ls -Recurse
如果您也想递归转换子目录中的所有文件,也可以使用。
然后,我们将这些过滤器过滤到我们想要转换的文件类型 - 例如“avi”。
ls | Where { $_.Extension -eq ".avi" }
之后,我们将通过一个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”文件,只需替换引号中的三个内容以决定您想要的转换类型,并随时在ForEach
.
您可以更进一步并添加Remove-Item
到末尾以自动删除旧文件。
如果ffmpeg
不在您的路径中,并且它实际上在您当前所在的目录中,请写./ffmpeg
在那里而不是ffmpeg
.
希望这对任何人都有帮助。
如果你有 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
根据需要。GNU 并行列在大多数 Linux 发行版的存储库中的一个包中,通常称为parallel
.
我知道这可能是多余的,但我使用这个脚本来批量转换文件。
old_extension=$1
new_extension=$2
for i in *."$old_extension";
do ffmpeg -i "$i" "${i%.*}.$new_extension";
done
需要 2 个参数使其更灵活:
- 您要转换的扩展名
- 您要转换为的新扩展名
我为它创建了一个别名,但您也可以像这样手动使用它:
sh batch_convert.sh mkv mp4
这会将所有mkv
文件转换为mp4
文件。
如您所见,它的用途更广泛。只要ffmpeg
可以转换它就可以指定任意两个扩展名。
以下脚本在 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
示例调用:
$ 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
示例调用:
$ sh ffmpeg-batch-convert.sh mp3 wav delete
我用它来为 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"
)
有点像代码高尔夫,但由于到目前为止几乎所有的答案都是 bash(除了一个孤独的 cmd 一个),这是一个使用 powershell的windows 跨平台命令(因为太棒了):
ls *.avi|%{ ffmpeg -i $_ <ffmpeg options here> $_.name.replace($_.extension, ".mp4")}
您可以将 *.avi 更改为与您的源素材匹配的任何内容。
视窗:
@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,但除非您有一个非常好的扬声器系统,否则它毫无价值 imo
只有这个对我有用,请注意您必须手动创建 ffmpeg.exe 文件所在的“newfiles”文件夹。
转换. 文件到 .wav 音频代码:
for %%a in ("*.*") do ffmpeg.exe -i "%%a" "newfiles\%%~na.wav"
pause
即,如果您想将所有 .mp3 文件转换为 .wav 更改("*.*")
为("*.mp3")
.
该脚本的作者是:
https://forum.videohelp.com/threads/356314-How-to-batch-convert-multiplex-any-files-with-ffmpeg
希望它有所帮助。
此外,如果您想在子文件夹中进行相同的转换。这是递归代码。
for /R "folder_path" %%f in (*.mov,*.mxf,*.mkv,*.webm) do (
ffmpeg.exe -i "%%~f" "%%~f.mp4"
)
对于咯咯笑,这是fish-shell中的解决方案:
for i in *.avi; ffmpeg -i "$i" (string split -r -m1 . $i)[1]".mp4"; end
使用多核,这是最快的方式,(使用并行):
parallel "ffmpeg -i {1} {1.}.mp4" ::: *.avi
这将从当前目录中的所有 jpg 文件创建 mp4 视频。
echo exec("ffmpeg -framerate 1/5 -i photo%d.jpg -r 25 -pix_fmt yuv420p output.mp4");
我在 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
这将转换为临时文件,然后替换原始文件,因此名称在转换后保持不变。
我需要所有视频都使用相同的编解码器进行合并,
所以这种转换是 mp4 到 mp4
,它在 zsh 中,但应该很容易转换为 bash
for S (*.mp4) { ffmpeg -i $S -c:v libx264 -r 30 new$S }
Bash 对我来说很糟糕,所以在 Linux/Mac 下,我更喜欢 Ruby 脚本:
(找到文件夹中的所有文件,然后将其从rmvb/rm
格式转换为mp4
格式)
# filename: run.rb
Dir['*'].each{ |rm_file|
next if rm_file.split('.').last == 'rb'
command = "ffmpeg -i '#{rm_file}' -c:v h264 -c:a aac '#{rm_file.split('.')[0]}.mp4'"
puts "== command: #{command}"
`#{command}`
}
你可以运行它: ruby run.rb
如果您想要使用 ffmpegX 进行批处理的图形界面,请尝试Quick Batcher。它是免费的,并且会使用您最后的 ffmpegX 设置来转换您放入其中的文件。
请注意,您不能将文件夹拖放到 Quick Batcher。因此,选择文件,然后将它们放入 Quick Batcher。
尚未建议的另一个简单解决方案是使用xargs
:
ls *.avi | xargs -i -n1 ffmpeg -i {} "{}.mp4"
一个小缺陷是输出文件的笨拙命名(例如input.avi.mp4
)。一个可能的解决方法可能是:
ls *.avi | xargs -i -n1 bash -c "i={}; ffmpeg -i {} "\${i%.*}.mp4"
"
这就是我用来将 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 文件。
调用我的(为你的更改)ffmpeg,传递输入名称,设置用于通过锐化重新缩放。我可能不需要 CRF 和“ -b:v 1024k
”...
输出文件是输入文件减去扩展名,mp4 作为新的扩展名。
对于 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"
我为此案例开发了python包。
https://github.com/developer0hye/BatchedFFmpeg
您可以轻松安装和使用它。
pip install batchedffmpeg
batchedffmpeg * -i folder * output_file
执行此操作的小 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' ) );
}