저는 ffmpeg를 사용하여 다양한 스트리밍 사이트에서 다운로드한 일부 비디오를 hevc로 인코딩합니다. Windows에서는 배치 파일을 사용하여 이러한 파일을 변환합니다.
FOR /F "tokens=*" %%G IN ('dir /b *.mp4') DO ffmpeg -n -i "%%G" -c:v libx265 -crf 22 -c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio "%%~nG.mkv"
이러한 파일 중 일부는 비트 전송률이 매우 낮으므로 해당 파일은 건드리고 싶지 않습니다. ffmpeg에서 이 파일을 건너뛸 수 있는 방법이 있나요? 또는 ffprobe
명령을 사용하여 비트 전송률을 얻고 건너뛰는 데 사용하는 것과 같이 배치 파일에 포함할 수 있는 명령입니다 .
답변1
@echo off
cd /d "%~dp0" && setlocal enabledelayedexpansion
set "_ffmpeg=F:\2020-SU\Q1569837\ffmpeg\bin\ffmpeg.exe"
set "_ffprobe=F:\2020-SU\Q1569837\ffmpeg\bin\ffprobe.exe"
for %%# in (*.mp4)do for /f tokens^=2^,6^delims^=^,^ %%i in (
'2^>^&1 "!_ffprobe!" -show_entries stream^=bit_rate "%%~f#" ^| "%__APPDIR__%findstr.exe" /e [0-9].kb/s
')do if %%~j gtr 349 2>&1 ("!_ffmpeg!" -y -i "%%~f#" -hide_banner -v error -stats -c:v libx265 -crf 22 ^
-c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio "%%~n#.mkv"
)else set/a "_c+=1+0" && <con: call set "_skp_!_c!=Skipped File: %%~nx# Duration: %%~i Bit Rate: %%~j"
echo;& (for /f tokens^=2^delims^=^= %%i in ('set _skp_ 2^>nul')do echo\%%~i) & %__APPDIR__%timeout.exe -1 & endlocal
- 산출:
x265 [info]: HEVC encoder version 3.4+2-73ca1d7be377
x265 [info]: build info [Windows][GCC 9.3.1][64 bit] 8bit+10bit
x265 [info]: using cpu capabilities: MMX2 SSE2Fast LZCNT SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
x265 [info]: Main profile, Level-3.1 (Main tier)
x265 [info]: Thread pool created using 4 threads
x265 [info]: Slices : 1
x265 [info]: frame threads / pool features : 2 / wpp(12 rows)
x265 [info]: Coding QT: max CU size, min CU size : 64 / 8
x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
x265 [info]: ME / range / subpel / merge : hex / 57 / 2 / 3
x265 [info]: Keyframe min / max / scenecut / bias : 23 / 250 / 40 / 5.00
x265 [info]: Lookahead / bframes / badapt : 20 / 4 / 2
x265 [info]: b-pyramid / weightp / weightb : 1 / 1 / 0
x265 [info]: References / ref-limit cu / depth : 3 / off / on
x265 [info]: AQ: mode / str / qg-size / cu-tree : 2 / 1.0 / 32 / 1
x265 [info]: Rate Control / qCompress : CRF-22.0 / 0.60
x265 [info]: tools: rd=3 psy-rd=2.00 early-skip rskip mode=1 signhide tmvp
x265 [info]: tools: b-intra strong-intra-smoothing lslices=4 deblock sao
frame= 1440 fps= 55 q=29.8 Lsize= 2570kB time=00:01:00.11 bitrate= 350.3kbits/s speed=2.32x
x265 [info]: frame I: 6, Avg QP:22.93 kb/s: 1138.86
x265 [info]: frame P: 705, Avg QP:25.55 kb/s: 498.87
x265 [info]: frame B: 729, Avg QP:28.95 kb/s: 98.52
x265 [info]: Weighted P-Frames: Y:0.9% UV:0.6%
x265 [info]: consecutive B-frames: 58.8% 11.0% 11.4% 6.6% 12.2%
encoded 1440 frames in 25.96s (55.47 fps), 298.86 kb/s, Avg QP:27.26
Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315
Skipped File: HVDC Light - ABB 3D.mp4 Duration: 00:03:32.16 Bit Rate: 336
관찰: 1있다두 개의 공백~ 사이^=^,^⟵⟶%%i안에: delims^=^,^spacespace%%i
for %%# in (*.mp4)do for /f tokens^=2^,6^delims^=^,^spacespace%%i in (...
1.- 재택근무: 시나리오에 맞는 방식으로 아래 변수를 바꾸고 bat 폴더로 이동합니다.
set "_ffmpeg=F:\2020-SU\Q1569837\ffmpeg\bin\ffmpeg.exe"
set "_ffprobe=F:\2020-SU\Q1569837\ffmpeg\bin\ffprobe.exe"
cd /d "%~dp0"
rem :: if your *.pm4 files are not in the same directory
rem :: as your bat file, use the full path to drive/folder
rem :: Example for drive D: folder/subfolder \Media\MP4\Convert
cd /d "D:\Midia\MP4\Convet"
2.이 배치는 다중을 사용합니다 for loop
. 작동하려면 Deleyed Expansion
변수가 런타임에 업데이트/확장된 값을 수신하도록 활성화해야 합니다.
Setlocal EnableDelayedExpansion
삼.불행하게도 당신의 현재for /f ... dir .mp4 ...
별로 도움이 되지 않으므로 for
모든 것을 얻을 수 있는 간단한 것으로 대체하십시오..mp4
루프에 나열됩니다.
for %%# in (*.mp4)do ....
4.추가 항목을 사용 하여 mp4 파일의 전체 경로/이름( )을 얻은 이 루프 변수(에서)를 사용 하고 이 루프를 이미 정의된 입력으로 전달합니다 (설명됨).for /f
1st/for/var==%%#
%%~f#
ffprobe
항목 5.), 해당 명령에서 사용할 토큰 및 구분 기호입니다.
for /f tokens^=2^,6^delims^=^,^ %%i in (ffmprobe ... %%~f# ...
5.그만큼ffprobe
루프 에 사용되는 명령은 다음과 같습니다for /f
..\ffprobe.exe -show_entries stream=bit_rate "Google Chrome - Now Everywhere.mp4"
6.스위치 를 사용하여 필터링할 출력 으로 StdErr
리디렉션 하는 것부터 시작합니다.StdOut
ffprobe
findstr
/End of a line
regex
숫자 ([0-9]
)를 문자열과 연결 .kb/s
하고 적절한 스케이핑을 사용합니다.for
고리:
2^>^&1 "!_ffprobe!" -show_entries stream^=bit_rate "%%~f#" ^| "%__APPDIR__%findstr.exe" /e [0-9].kb/s
7.위의 확장 명령을 이스케이프 없이 실행하면 다음과 같은 결과가 발생합니다.
2>&1 ..\ffprobe.exe -show_entries stream=bit_rate "Google Chrome - Now Everywhere.mkv" | "%__APPDIR__%findstr.exe" /e [0-9].kb/s
8.필터로 처리된 위 명령의 출력은 findstr
다음과 같습니다.
지속 시간: 00:01:00.08, 시작: -0.007000, 비트 전송률: 350kb/s
9.필터로 처리된 위 명령의 출력은 findstr
다음과 같습니다.
지속 시간: 00:01:00.08, 시작: -0.007000, 비트 전송률: 350kb/s
10.여러 구분 기호를 사용하면%%i
그리고%%j
출력은00:01:00.08
그리고350
: 마지막 명령 출력을 위한 것입니다.00:01:00.08
그리고350
:
... for /f tokens^=2^,6^delims^=^,^space %%i in (...
Duration: 00:01:00.08, start: -0.007000, bitrate: 350 kb/s
11.한계 값이 다음과 같다고 가정합니다.350
(포함한if
) 바이트 속도의 경우 작업 부분에서 일부 옵션을 사용해야 합니다 .
if %%~j > Bit_Rate ∕∕ the same: if %%~j > 349 (349 exclusive)
if %%~j ≥ Bit_Rate ∕∕ the same: if %%~j ≥ 350 (350 inclusive)
set "_bit_rate=349"
if %%~j > %_bit_rate% ∕∕ the same: if %%~j > 349 (349 exclusive)
set "_bit_rate=350"
if %%~j ≥ %_bit_rate% ∕∕ the same: if %%~j ≥ 350 (350 inclusive)
if LSS - Less Than if [integer or int(var)] < [integer or int(var)]
if GTR - Greater Than if [integer or int(var)] > [integer or int(var)]
if LEQ - Less Than or Equals if [integer or int(var)] ≤ [integer or int(var)]
if GEQ - Greater Than or Equals if [integer or int(var)] ≥ [integer or int(var)]
12.결과if
~이다true
또는false
, 사례에 따라 작업을 수행합니다. 교훈적인 목적으로 현재 파일을true
사례:
if %%~j GTR 349 (
case true
ffmpeg transcode file mp4
) else (
case false
skip this file .mp4
save the full path name
)
if %%~j gtr 349 2>&1 ("!_ffmpeg!" -y -i "%%~f#" -hide_banner -v error -stats -c:v libx265 -crf 22 ^ -c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio "%%~n#.mkv"
관찰:2캐릭터:space^는 줄 끝, 줄 바꿈 바로 옆에 있습니다. 여기서 실행 시 명령 해석기는 적용된 줄 바꿈을 이스케이프 처리하여 이를 단일 줄로 처리합니다.
13.바이트율이 낮은 파일의 경우,false
의 경우if
명령을 사용하면 제외된 파일을 저장하는 작업이 있습니다.ffmpeg
변환되며 실행이 끝나면 나열됩니다.
if %%~j GTR 349 (
case true
ffmpeg transcode file mp4
) else (
case false
skip this file .mp4
save the full path name
)
관찰:3그만큼
if
다음과 같은 다양한 레이아웃에서도 작동합니다.if %%~j GTR 349 (case true ffmpeg transcode file mp4 ) else ( case false skip this file .mp4 save the full path name )
if %%~j GTR 349 (case true && ffmpeg transcode file mp4 ) else ( case false && skip this file .mp4 && save the full path name )
if %%~j GTR 349 (case true && ffmpeg transcode file mp4 )else case false && skip this file .mp4 && save the full path name
14.의 값을 사용하여%%~f#
,%%~i
그리고%%~j
변수는 각각 현재 파일의 경로 및 전체 이름, 지속 시간 및 비트 전송률입니다. 카운터( set/a "_c+=1+0"
)를 쉽게 추가할 수 있으며 실행 시간에 증가하여 제외된 파일의 정보를 하나씩 생성/정의합니다. 변환:
)else set/a "_c+=1+0" && <con: call set "_skp_!_c!=Skipped File: %%~nx# Duration: %%~i Bit Rate: %%~j"
%%~f# == Live_TV_-_Bloomberg.mp4
%%~i == 00:00:36.42
%%~j == 315
set "_c+=1+0" && call set "_skp_1=Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315"
15.set 명령은 변수 및 값 목록에도 사용할 수 있으며set user
, 정의된 모든 변수user+(strings)
다음과 같이 나열됩니다.
>set USER
USERDOMAIN=LAME_SLUG
USERDOMAIN_ROAMINGPROFILE=LAME_SLUG
USERNAME=ecker
USERPROFILE=C:\Users\ecker
16.마지막 줄에는for /f
루프에서는 이름으로 정의된 각 변수를 에코하는 데 사용됩니다._skip_*
, 실행 중에 무시된 파일을 저장하여 정의되었으며 이 루프는 기호 뒤에 오는 모든 것을 가져옵니다.=
(2차/tokens^=2
):
for /f tokens^=2^delims^=^= ... set _skp_1 .... echo\%%~i
_skp_1=Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315
↓
tokens^=2 ⇄ Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315
echo;& (for /f tokens^=2^delims^=^= %%i in ('set _skp_')do echo\%%~i)...
17.bat 파일에서 마지막 부분의 두 번째와 마지막 부분은 루프가 발생하도록 하고(격리) 건너뛴 모든 파일을 나열한 후에만 일시 중지/무기한 시간 초과되어 일부 키를 누를 때까지 기다리므로/ setlocal을 마무리하고 실행을 종료합니다.
1st part: (for /f .....)
2nd part: %__APPDIR__%timeout.exe -1 & endlocal
echo; & (for /f tokens^=2^delims^=^= %%i in ('set _skp_')do echo\%%~i) & %__APPDIR__%timeout.exe -1 & endlocal
18.발생할 수 있는 오류 메시지를 방지하려면(Environment variable _skip_ not defined
), 에서 파일을 무시하지 않은 경우에는 if
다음을 추가하세요.2^>nul
~에'set _skip_*2^>nul'
, 마지막 루프 내부for
:
(for /f tokens^=2^delims^=^= %%i in ('set _skp_ 2^>nul')do echo\%%~i)do...
- Obs.4여기서는
echo;
건너뛴 파일을 나열하기 전에 하나의 분리주의 라인을 생성하는 데만 사용됩니다.
- 기존/교훈적 레이아웃의 동일한 코드:
@echo off
cd /d "%~dp0"
setlocal enabledelayedexpansion
set "_ffmpeg=F:\2020-SU\Q1569837\ffmpeg\bin\ffmpeg.exe"
set "_ffprobe=F:\2020-SU\Q1569837\ffmpeg\bin\ffprobe.exe"
for %%# in (*.mp4) do (
for /f "tokens=2,6 delims=, " %%i in ('2^>^&1 "!_ffprobe!" -show_entries stream^=bit_rate "%%~f#" ^| "%__APPDIR__%findstr.exe" /e [0-9].kb/s') do (
if %%~j gtr 3200 (
2>&1 "!_ffmpeg!" -y -i "%%~f#" -hide_banner -v error -stats -c:v libx265 -crf 22 -c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio "%%~n#.mkv"
) else (
set /a "_c+=1+0"
set "_skp_!_c!=Skipped File: %%~nx# Duration: %%~i Bit Rate: %%~j"
)
)
)
echo.
for /f "tokens=2 delims==" %%i in ('2^>nul set _skp_')do echo\%%~i
%__APPDIR__%timeout.exe -1
endlocal