이메일 등으로 보낼 수 있도록 동영상 크기를 줄이고 싶습니다. 나는 이 질문을 보았습니다.ffmpeg를 사용하여 비디오 크기를 줄이는 방법은 무엇입니까?거기서 나는 그것을 줄이는 방법에 대한 좋은 조언을 얻었습니다. 문제는 비트 전송률을 수동으로 계산해야 한다는 것입니다. 그리고 이 작업을 하면서 수동으로 시행착오를 거쳐야 합니다.
ffmpeg
비디오 크기를 줄이기 위해 사용하거나 다른 도구를 사용할 수 있는 좋은 방법이 있습니까?표적크기?
Frostschutz의 의견을 참고하세요:
크기에 대해 너무 걱정하고 비디오 길이/해상도/프레임 속도/내용에 관계없이 고정된 파일 크기를 선택하면 대부분 만족스러운 결과를 얻을 수 없습니다. 이메일 링크를 통해 어딘가에 업로드하십시오. 인코딩해야 한다면 품질 수준을 설정하고 비트 전송률을 동적으로 유지하세요. 크기 요구 사항을 충족할 수 없는 것이 확실한 경우 인코딩을 취소하고 이에 따라 품질 수준을 조정하세요. 헹구고 반복하십시오.
전반적으로 좋은 조언이지만 내 사용 사례에는 맞지 않습니다. 외부 링크에 업로드하는 것은 기술적 한계로 인해 옵션이 아니며, 그 중 하나는 수신자가 http 액세스 권한이 없다는 것입니다.
또한 내가 찾고 있는 것이 아니라는 점을 분명히 할 수도 있습니다.정확히내가 지정한 크기. 내가 원하는 값에 매우 가깝다면(5% 또는 10% 더 낮을 수도 있음) 충분하지만 그렇지 않을 것이라는 보장이 있어야 합니다.초과하다내 목표 한도.
답변1
@philip-couling의 답변은 비슷하지만 몇 가지 부분이 누락되었습니다.
- 비트 전송률을 얻으려면 필요한 크기(MB)에 8을 곱해야 합니다.
- 비트 전송률의 경우 1Mb/s = 1000kb/s = 1000000b/s; 승수는 1024가 아닙니다(1024B/s인 KiB/s라는 또 다른 접두사가 있지만 ffmpeg에서는 이를 사용하지 않는 것 같습니다).
- 정수가 아닌 숫자를 자르거나 반올림하면
length
(정확한 값을 사용하거나 반올림하는 대신) 파일 크기가 대상 크기를 약간 초과하게 됩니다. - 이
-b
플래그는 평균 비트 전송률을 지정합니다. 실제로 인코더는 비트 전송률을 약간 높이며 결과는 목표 크기를 초과할 수 있습니다. 그러나 다음을 사용하여-maxrate
최대 비트 전송률을 지정할 수 있습니다.-bufsize
내 사용 사례에서는 하드코딩된 오디오 비트 전송률을 갖고 그에 따라 비디오를 조정하고 싶습니다. (이 또한 더 안전한 것 같습니다. -b
ffmpeg의 플래그가 비디오 및 오디오 스트림에 대한 비트 전송률을 함께 지정하는지 100% 확실하지 않습니다.)
이 모든 것을 고려하여 25MB로 엄격하게 제한됩니다.
file="input.mp4"
target_size_mb=25 # 25MB target size
target_size=$(( $target_size_mb * 1000 * 1000 * 8 )) # target size in bits
length=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file"`
length_round_up=$(( ${length%.*} + 1 ))
total_bitrate=$(( $target_size / $length_round_up ))
audio_bitrate=$(( 128 * 1000 )) # 128k bit rate
video_bitrate=$(( $total_bitrate - $audio_bitrate ))
ffmpeg -i "$file" -b:v $video_bitrate -maxrate:v $video_bitrate -bufsize:v $(( $target_size / 20 )) -b:a $audio_bitrate "${file}-${target_size_mb}mb.mp4"
-maxrate
최대 비트 전송률을 제한 하면 -bufsize
평균 비트 전송률이 반드시 감소하므로 내 테스트에서 비디오는 목표 크기보다 5~10% 정도 낮습니다(다양한 목표 크기의 20초 비디오에서). 의 값이 -bufsize
중요합니다. 위에 사용된 계산된 값(대상 크기 기준)이 제가 추측한 최선의 값입니다. 너무 작으면 품질이 크게 떨어지고 목표 크기보다 약 50% 정도 작아지지만, 너무 크면 목표 크기를 초과할 수도 있다고 생각하시나요?
-maxrate
엄격한 최대 파일 크기가 없는 경우 및를 제거하면 인코더에 더 많은 유연성을 제공하기 위해 품질이 향상되지만 -bufsize
테스트 결과 비디오가 대상 크기를 5% 초과할 수 있습니다.자세한 내용은 설명서를 참조하세요., 여기에 다음 경고가 표시됩니다.
참고: 비디오를 인코딩하기 어려운 경우 비트 전송률을 제한하면 출력 품질이 저하될 수 있습니다. 대부분의 경우(예: 보관용 파일 저장) 인코더가 적절한 비트 전송률을 선택하도록 하는 것은 일정한 품질 또는 CRF 기반 인코딩입니다.
다음 코드를 사용하여 재사용 가능한 bash 함수를 선언할 수 있습니다.
ffmpeg_resize () {
file=$1
target_size_mb=$2 # target size in MB
target_size=$(( $target_size_mb * 1000 * 1000 * 8 )) # target size in bits
length=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file"`
length_round_up=$(( ${length%.*} + 1 ))
total_bitrate=$(( $target_size / $length_round_up ))
audio_bitrate=$(( 128 * 1000 )) # 128k bit rate
video_bitrate=$(( $total_bitrate - $audio_bitrate ))
ffmpeg -i "$file" -b:v $video_bitrate -maxrate:v $video_bitrate -bufsize:v $(( $target_size / 20 )) -b:a $audio_bitrate "${file}-${target_size_mb}mb.mp4"
}
ffmpeg_resize file1.mp4 25 # resize `file1.mp4` to 25 MB
ffmpeg_resize file2.mp4 64 # resize `file2.mp4` to 64 MB
답변2
댓글을 달 만큼 평판이 좋지 않습니다. Windows/Dos 배치 파일로 작동하도록 위의 @tobek 코드를 조정했습니다.
@echo off
setlocal
if "%~1" == "" (
echo Usage:
echo.
echo %0 filename.mp4
echo or
echo %0 filename.mp4 25
echo (25 = 25MB^)
goto end
)
set target_mb=%2
if "%~2" == "" (
rem # default
set target_mb=25
)
set file=%1
set /a target_size=%target_mb% * 1000 * 1000 * 8
for /f %%c in ('ffprobe -v error -show_entries format^=duration -of default^=noprint_wrappers^=1:nokey^=1 "%file%"') do set length=%%c
for /f "tokens=1 delims=." %%n in ('echo %length%') do set length_round_up=%%n
set /a length_round_up=%length_round_up% + 1
rem # 128k bit rate
set /a audio_bitrate=128 * 1000
set /a total_bitrate=%target_size% / %length_round_up%
set /a video_bitrate=%total_bitrate% - %audio_bitrate%
set /a bufsize=%target_size% / 20
for %%f in ("%file%") do (
set filedrive=%%~df
set filepath=%%~pf
set filename=%%~nf
set fileextension=%%~xf
)
set file_output=%filedrive%%filepath%%filename%-out%fileextension%
ffmpeg -i "%file%" -b:v %video_bitrate% -maxrate:v %video_bitrate% -bufsize:v %bufsize% -b:a %audio_bitrate% "%file_output%"
:end
답변3
면책조항: 완벽하지는 않은 것 같습니다. 약간 더 커집니다.
다른 두 가지 답변을 합치는 것은 비교적 간단합니다.
ffprobe
기간을 찾고 셸에서 계산을 수행하는 데 사용할 수 있는 10MB 파일(10485760바이트)이 필요하다고 가정해 보겠습니다 .
ffprobe는 소수점 이하 자릿수를 보고하므로 쉘 산술 오류가 발생할 수 있으므로 주의하십시오. 나는 소수점 이하 자릿수를 제거하곤 했습니다 ${length%.*}
:
size=10485760
length=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4)
ffmpeg -i input.mp4 -b $(( $size / ${length%.*} )) output.mp4