Làm thế nào để bạn chuyển đổi toàn bộ một thư mục với ffmpeg?


187

Làm thế nào để bạn chuyển đổi toàn bộ thư mục / thư mục với ffmpeg thông qua dòng lệnh hoặc với một tập lệnh bó?

Câu trả lời:


172

Câu trả lời trước sẽ chỉ tạo 1 tệp đầu ra gọi là out.mov. Để tạo một tệp đầu ra riêng cho mỗi phim cũ, hãy thử điều này.

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

24
Nếu bạn giống tôi và có nhiều khoảng trắng (và một vài ký tự có vấn đề khác) trong tên tệp của bạn, tôi khuyên bạn nên thêm dấu ngoặc kép: ffmpeg -i "$ i" "$ name.mov";
Pif

7
Tôi đang gặp lỗii was unexpected at this time.
Keavon

5
do name=`echo "${i%.*}"`;sẽ làm việc trên tên tệp có dấu chấm (và dấu cách) trong đó.
Nepoxx

8
Wow, câu trả lời này là quá phức tạp. Xem một trong những câu trả lời một dòng.
foobarbiru

2
hỗ trợ này .battrong windows?
Jazuly

289

Đối với LinuxmacOS, điều này có thể được thực hiện trong một dòng, sử dụng mở rộng tham số để thay đổi phần mở rộng tên tệp của tệp đầu ra:

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

1
Điều này là hoàn hảo, cảm ơn bạn! Đây là lệnh đầy đủ mà cuối cùng đã làm việc rất tốt cho tôi: cho tôi trong * .avi; làm ffmpeg -i "$ i" -c: aac -b: a 128k -c: v libx264 -crf 20 "$ {i% .avi} .mp4"; xong
Phil Kulak

1
@Junaid 1) Đảm bảo sử dụng tên khác cho tệp đầu ra so với đầu vào hoặc đầu ra sang thư mục khác, vì ffmpegkhông thể nhập và xuất ra cùng một tệp. 2) Tôi không chắc các lệnh Bash có hoạt động trên Windows 10 hay không. Có lẽ tôi nên thêm vào câu trả lời rằng nó được nhắm mục tiêu vào các hệ thống có thể sử dụng Bash như Linux và macOS. lxs cung cấp một câu trả lời Windows cho câu hỏi này.
llogan

3
Câu trả lời tuyệt vời. Hoạt động với tên tập tin với không gian quá!
wvducky

1
Đây phải là câu trả lời hàng đầu. Phải thừa nhận rằng, lời giải thích cho lý do tại sao {$ i%. *} Không đơn giản, nhưng nếu bạn có thể đặt nó sang một bên và chỉ cần "sử dụng nó", bạn có thể nhanh chóng sửa đổi cho phù hợp. Ví dụ: tôi đã chuyển đổi hàng trăm .mp4 (với tên tệp có khoảng trắng và ký tự đặc biệt) sang định dạng nhỏ hơn bằng cách sử dụng: for i in .mp4; làm ffmpeg -i "$ i" -s 512x288 -c: một bản sao "$ {i%. } .m4v"; xong
Tony M

1
Để tiến thêm một bước, bạn có thể sử dụng thay thế tham số Bash nếu bạn muốn thay thế chuỗi "x265" bằng "x264" nếu bạn chuyển mã từ H.265 sang H.264, đây là trường hợp sử dụng phổ biến. 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
Travis

68

Và trên Windows:

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

19
nếu bạn chạy lệnh này trong tệp bó (.bat), bạn cần tăng gấp đôi% dấu => %%
hB0

Bất kỳ ý tưởng làm thế nào để chạy lệnh này nhưng sao chép vào một tệp mới bao gồm siêu dữ liệu của tệp gốc?
Barryman9000

@ Barryman9000 điều này đã có từ lâu nhưng tôi nghĩ có một tùy chọn tệp đầu ra mà bạn có thể vượt qua
lxs

@lxs cảm ơn đã theo dõi. Tôi đã kết thúc việc đó với Powershell bằng cách thay đổi tên của tệp mới thành ngày của tệp gốc được tạo stackoverflow.com/a353671099/197472
Barryman9000

Đã sử dụng nó để loại bỏ siêu dữ liệu. Nhưng nó đang cho tôi quyền truy cập bị từ chối lỗi. Vì vậy, tôi đã thay đổi tên tệp đầu ra với một không gian thừa để làm cho nó một tệp mới. 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

Kịch bản bash một dòng sẽ dễ thực hiện - thay thế *.avibằng kiểu tệp của bạn:

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

Bộ mã hóa mặc định cho .mov là libx264 (nếu có), nhưng bộ mã hóa này bỏ qua -qscale. Xóa nó và sử dụng các cài đặt mặc định hoặc sử dụng -crfthay thế (mặc định là -crf 23).
llogan

1
Nếu có bất kỳ khoảng trắng nào trong tên tệp, lệnh sẽ thất bại vì phần con basenameđược sao lưu không được trích dẫn. Đây chính xác là lý do tại sao bash có phần mở rộng shell thay thế: for i in * .avi; làm ffmpeg -i "$ i" -qscale 0 "$ (tên cơ sở" $ i ".avi)". Mov; xong
Calimo

nhờ @Calimo hoàn toàn đồng ý - tôi đã cập nhật câu trả lời của tôi
lòng đỏ

22

Để chuyển đổi với thư mục con sử dụng, vd

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

Tôi đã sử dụng điều này, kết hợp với câu trả lời này để chuyển đổi VTT sang SRT, để đạt hiệu quả cao. find -name "*.vtt" -exec ffmpeg -i {} {}.srt \;
grooveplex

Tôi thực hiện lệnh này, với một chút sửa đổi để chuyển đổi tất cả mp4 sang mp3:find *.mp4 -exec ffmpeg -i {} {}.mp3 \;
swdev

1
Hoặc, nếu bạn muốn chuyển đổi nhiều loại tệp:find . -name *.ogg -or -name *.wma -exec ffmpeg -i {} {}.mp3 \;
bonh

Chuyển đổi tất cả các tệp wma sang mp3 và sau khi xóa chúng:find . -name *.wma -exec ffmpeg -i {} {}.mp3 \; -exec rm {} \;
Panagiotis

20

Cho cửa sổ:

Ở đây tôi đang chuyển đổi tất cả các tệp (.mp4) thành các tệp (.mp3).
Chỉ cần mở cmd, goto thư mục mong muốn và gõ lệnh.

Phím tắt: (tùy chọn)
1. Xem thư mục chứa tệp (.mp4) của bạn
2. Nhấn Shift và nhấp chuột trái và chọn "Mở cửa sổ PowerShell tại đây"
hoặc "Mở cửa sổ nhắc lệnh ở đây"
3. Nhập "cmd" [LƯU Ý : Bỏ qua bước này nếu nó trực tiếp mở cmd thay vì PowerShell]
4. Chạy lệnh

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

Nếu bạn muốn đặt tệp này vào một tệp bó trên Windows 10, bạn cần sử dụng %% i.


17

Đối với bất kỳ ai muốn chuyển đổi hàng loạt bất cứ thứ gì với ffmpeg nhưng muốn có giao diện Windows thuận tiện, tôi đã phát triển giao diện người dùng này:

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

Nó thêm vào ffmpeg một giao diện thời trang cửa sổ, thanh tiến trình và thông tin thời gian còn lại, các tính năng tôi luôn bỏ qua khi sử dụng ffmpeg.


Ok đây là một dự án tốt đẹp! Tôi đã theo đuổi cái đuôi của mình trong một giờ khi cố gắng để ffmpeg chấp nhận một đường dẫn hoàn hảo tương đối trong Windows và điều này khiến nó cảm thấy như gian lận. EDIT: tôi đã sử dụng điều này để chuyển đổi .xwm thành .flac
semtex41

6

Nếu bạn có GNU song song, bạn có thể chuyển đổi tất cả các tệp .avi bên dưới vid_dirthành mp4 song song, sử dụng tất cả ngoại trừ một trong các lõi CPU của bạn với

find vid_dir -type f -name '*.avi' -not -empty -print0 |
    parallel -0 -j -1 ffmpeg -loglevel fatal -i {} {.}.mp4

Để chuyển đổi từ / sang các định dạng khác nhau, thay đổi '*.avi'hoặc .mp4khi cần thiết. GNU song song được liệt kê trong hầu hết các kho lưu trữ phân phối Linux trong một gói thường được gọi parallel.


bạn không thể làm điều tương tự bằng cách thêm !vào phần cuối của bất kỳ lớp lót bash nào?
stib

3

Tôi biết điều này có thể là dư thừa nhưng tôi sử dụng tập lệnh này để chuyển đổi tập tin hàng loạt.

old_extension=$1
new_extension=$2

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

Phải mất 2 đối số để làm cho nó linh hoạt hơn:

  1. tiện ích mở rộng bạn muốn chuyển đổi từ
  2. tiện ích mở rộng mới mà bạn muốn chuyển đổi thành

Tôi tạo một bí danh cho nó nhưng bạn cũng có thể sử dụng nó theo cách thủ công như thế này:

sh batch_convert.sh mkv mp4

Điều này sẽ chuyển đổi tất cả các mkvtập tin thành mp4tập tin.

Như bạn có thể thấy nó linh hoạt hơn một chút. Miễn là ffmpegcó thể chuyển đổi nó, bạn có thể chỉ định bất kỳ hai phần mở rộng.


Đó là điều tốt nhất
Andreas Prang

3

Bắt một chút giống như golf mã ở đây, nhưng kể từ khi gần như tất cả các câu trả lời cho đến nay là bash (trừ một ai cmd cô đơn), đây là một cửa sổ chéo nền tảng lệnh đó sử dụng PowerShell (vì tuyệt vời):

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

Bạn có thể thay đổi * .avi thành bất cứ điều gì phù hợp với cảnh quay nguồn của bạn.


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

Xử lý hàng loạt flactệp vào mp3(an toàn cho tên tệp có dấu cách) bằng [1] [2]


2

các cửa sổ:

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

%~nd.2.mp3"
)

Đây là bitrate biến đổi của chất lượng 2, bạn có thể đặt nó thành 0 nếu bạn muốn nhưng trừ khi bạn có một hệ thống loa thực sự tốt, đó là imo vô giá trị


2

Tất nhiên, bây giờ PowerShell có đi cùng, được thiết kế đặc biệt để làm một cái gì đó chính xác như thế này cực kỳ dễ dàng.

Và, vâng, PowerShell cũng có sẵn trên các hệ điều hành khác ngoài Windows, nhưng nó được cài đặt sẵn trên Windows, vì vậy điều này sẽ hữu ích cho mọi người.

Trước tiên, bạn sẽ muốn liệt kê tất cả các tệp trong thư mục hiện tại, vì vậy, chúng tôi sẽ bắt đầu với:

ls

Bạn cũng có thể sử dụng ls -Recursenếu bạn muốn chuyển đổi đệ quy tất cả các tệp trong thư mục con.

Sau đó, chúng tôi sẽ lọc chúng xuống chỉ loại tệp chúng tôi muốn chuyển đổi - ví dụ: "avi".

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

Sau đó, chúng tôi sẽ chuyển thông tin đó cho FFmpeg thông qua a ForEach.

Đối với đầu vào của FFmpeg, chúng tôi sẽ sử dụng FullName- đó là toàn bộ đường dẫn đến tệp. Và đối với sản lượng FFmpeg của chúng tôi sẽ sử dụng Name- nhưng thay thế các .avivào cuối với .mp3. Vì vậy, nó sẽ trông giống như thế này:

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

Vì vậy, hãy đặt tất cả những thứ đó lại với nhau và đây là kết quả:

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

Điều đó sẽ chuyển đổi tất cả các tệp ".avi" thành các tệp ".mp3" thông qua FFmpeg, chỉ cần thay thế ba điều trong dấu ngoặc kép để quyết định loại chuyển đổi nào bạn muốn và thoải mái thêm bất kỳ đối số nào khác vào FFmpeg trong ForEach .

Bạn có thể tiến thêm một bước này và thêm Remove-Item vào cuối để tự động xóa các tệp cũ.

Nếu ffmpegkhông có trong đường dẫn của bạn và nó thực sự nằm trong thư mục bạn hiện đang ở, hãy viết./ffmpeg ở đó thay vì chỉffmpeg .

Hy vọng điều này sẽ giúp bất cứ ai.


1
PowerShell thật tuyệt, cảm ơn! Trong trường hợp bất kỳ ai khác gặp rắc rối khi chạy lệnh này: hãy đặt lệnh này vào một .ps1tệp chứ không phải .battệp. Bạn sẽ phải chạy Set-ExecutionPolicy RemoteSignedvới tư cách quản trị viên nếu bạn chưa bao giờ chạy tập lệnh PS trước đây.
sao vào

Chà, nói chung tôi chỉ nghĩ về việc chạy thẳng trong PowerShell, vì vậy tôi không thực sự nghĩ về điều đó! Mẹo tốt mặc dù!
ABPerson

1

Nếu bạn muốn giao diện đồ họa xử lý hàng loạt với ffmpegX, hãy thử Quick Batcher . Nó miễn phí và sẽ lấy các cài đặt ffmpegX cuối cùng của bạn để chuyển đổi các tệp bạn thả vào đó.

Lưu ý rằng bạn không thể kéo thả thư mục vào Quick Batcher. Vì vậy, chọn tập tin và sau đó đặt chúng thông qua Quick Batcher.


2
Phần mềm "Quick Batcher" chỉ dành cho hệ điều hành MAC
Mohammad ElNesr

1

Chỉ cái này hoạt động với tôi, xin lưu ý rằng bạn phải tạo thư mục "newfiles" theo cách thủ công nơi đặt tệp ffmpeg.exe.

Chuyển đổi . tập tin vào .wav âm thanh Mã:

for %%a in ("*.*") do ffmpeg.exe -i "%%a" "newfiles\%%~na.wav"
pause

tức là nếu bạn muốn chuyển đổi tất cả các tệp .mp3 sang .wav thay đổi ("*.*")thành("*.mp3") .

Tác giả của kịch bản này là:

https://forum.videohelp.com/threads/356314-How-to-batch-convert-multiplex-any-files-with-ffmpeg

hy vọng nó đã giúp.


0

Điều này sẽ tạo video mp4 từ tất cả các tệp jpg từ thư mục hiện tại.

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

0

Và đối với Windows, điều này không hoạt động

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

ngay cả khi tôi làm gấp đôi % .

Tôi thậm chí sẽ đề nghị:

-acodec ***libmp3lame***

cũng thế:

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

Đây có phải là một câu trả lời, hoặc một nỗ lực để đăng một câu hỏi mới như một câu trả lời? Trong trường hợp sau, vui lòng tạo một câu hỏi hoàn toàn mới thay vào đó, mặc dù có thể liên kết lại ở đây để làm nền.
tripleee

0

Đây là những gì tôi sử dụng để chuyển đổi hàng loạt avi thành 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"

Hoạt động tốt như một tệp cmd, chạy nó, vòng lặp tìm thấy tất cả các tệp avi trong thư mục đó.

gọi MY (thay đổi cho bạn) ffmpeg, chuyển tên đầu vào, các cài đặt để thay đổi kích thước với độ sắc nét. Tôi không cần CRF và " -b:v 1024k" ...

Tệp đầu ra là tệp đầu vào trừ phần mở rộng, với mp4 là phần mở rộng mới.


0

Tôi đang sử dụng một lớp lót này trong linux để chuyển đổi các tệp (thường là H265) thành thứ gì đó tôi có thể chơi trên Kodi mà không gặp vấn đề gì:

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

Điều này chuyển đổi thành một tệp tạm thời và sau đó thay thế bản gốc để các tên vẫn giữ nguyên sau khi chuyển đổi.


0

Ngoài ra nếu bạn muốn hội tụ tương tự trong các thư mục con. đây là mã đệ quy.

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

-1

tập lệnh php nhỏ để làm điều đó:

#!/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
Một câu trả lời phạm vi rất hạn chế vì người dùng phải cài đặt PHP trên máy của họ. Các dòng lệnh và câu trả lời tệp bó dễ dàng hơn nhiều và ít phức tạp hơn.
ProfK

2
@ProfK PHP là một trong những ngôn ngữ phổ biến nhất trên SO - thứ hai, câu trả lời của Isaac cho sh có phần không đáng tin, vì nó có thể đổi tên các tệp của bạn thành một cái gì đó khác với bản gốc, ví dụ, nó không lưu các dòng mới trong tên tệp. Kịch bản bat của lyx thậm chí còn tệ hơn, nó HOÀN TOÀN BỎ QUA bất kỳ tệp nào có dòng mới trong tên. không chắc chắn tại sao, thậm chí không có lỗi cú pháp hay bất cứ điều gì, nhưng nó đã xảy ra (đã thử nghiệm trên win10). kịch bản php của tôi không có vấn đề gì, nhờ escapeshellarg()và hoạt động cả trên windows và linux. tôi đồng ý một trường hợp cạnh của nó mặc dù.
hanshenrik

-1

Một giải pháp đơn giản khác chưa được đề xuất là sử dụng xargs:

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

Một cạm bẫy nhỏ là việc đặt tên lúng túng của các tệp đầu ra (ví dụ: input.avi.mp4 ). Một cách giải quyết có thể cho việc này có thể là:

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


shellcheck.net có một vài gợi ý liên quan đến ví dụ của bạn.
llogan

mywiki.wooledge.org/ParsingLs mặc dù bạn chỉ có thể thay thế lsbằng printf '%s\n'ở đây.
tripleee
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.