비디오 파일을 식별하고 일부 규칙에 따라 FFmpeg를 사용하여 트랜스코딩하는 일반 쉘 스크립트를 작성하는 방법은 무엇입니까?

비디오 파일을 식별하고 일부 규칙에 따라 FFmpeg를 사용하여 트랜스코딩하는 일반 쉘 스크립트를 작성하는 방법은 무엇입니까?

ffmpeg비디오 파일의 하위 폴더가 포함된 폴더를 읽고 HEVC로 인코딩되지 않은 파일을 선택하여 전달한 다음 입력과 출력 파일을 비교하는 간단한(몇 가지 명령만 실행) 스크립트를 얻으려고 합니다. 출력 크기가 더 크면 다음 파일로 이동하고, 크기가 더 작으면 원본 파일을 교체합니다.

내 논리는 이렇습니다.

  1. 순수 txt 목록을 준비합니다.

    find /folder -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" \) > log.txt
    
  2. txt를 다음으로 전달하세요.ffprobe

    ffprobe "log.txt" -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1
    

여기 ffprobe에서 행 1,2,3 등이 에서 수신되어야 하지만 단일 입력만 허용되므로 log.txt이를 수행하는 방법을 모르겠습니다 .ffprobe

  1. ffprobe목록을 실행하고 HEVC가 아닌 결과를 출력해야 합니다.log1.txt

  2. 트랜스코딩을 위해 시스템 폴더를 전달 log1.txt해야 하는 위치 입니다 . 작업 명령이 있는데 여기 구문은 단일 파일에 문제가 되지 않습니다.ffmpeg/tmpffmpeg

  3. 입력과 출력을 비교합니다. 입력이 출력보다 크면 교체합니다. 출력이 입력보다 크면 이를 버리고 다음으로 넘어갑니다.

내가 겪고 있는 문제는 주로 변수 전달(2. 참조) 및 명시적 전달(5.)과 관련이 있습니다. 해결책이 아닌 위의 문제를 처리하는 방법에 대한 몇 가지 지침이 필요합니다.

읽어 주셔서 감사합니다.

답변1

파일 목록을 생성하기 위해 find를 사용해서는 안 됩니다.find 출력을 구문 분석하는 것은 위험하므로 피해야 합니다.– 특히 공백이 포함된 파일 이름의 경우. 대부분의 작업을 수행하는 스크립트를 준비하고 find의 exec 인수를 통해 실행하는 것이 더 좋습니다(보호된 세미콜론이 필요하며 bash가 find 대신 와일드카드를 확장하는 것을 방지하기 위해 작은따옴표도 사용합니다).

find /folder -type f \( -iname '*.mkv' -o -iname '*.mp4' -o -iname '*.avi' \) -exec transcode.sh {} \;

파일에서 직접 ffprobe를 호출하고 출력을 grep으로 파이프하여 코덱 이름을 확인할 수 있습니다(원하는 코덱의 실제 이름을 알지 못하므로 조정하시기 바랍니다).

if ffprobe "$1" -hide_banner -loglevel panic -select_streams v:0 -show_entries stream=codec_name | grep -q 'hvec'
then
  # TODO: do transcoding
fi

트랜스코딩 후 다음을 수행할 수 있습니다.파일 크기 비교그리고 그에 따라 행동하십시오(다음에 스크립트를 실행할 때 파일을 다시 트랜스코딩하는 데 시간과 노력을 낭비하지 않도록 의도적으로 파일 스텁을 그대로 두었습니다).

if [[ $(stat -c%s "$f") -gt $(stat -c%s "$fhvec") ]]
then
  mv "$fhvec" "$f"
else
  truncate -s 0 "$fhvec"
fi

보다 일반적인 경고: 중요하지 않은 데이터(미리보기, 썸네일, 프록시)에 대해서만 이 작업을 수행하세요. HVEC는 강력한 인코더이지만 두 가지 다른 인코더의 압축 아티팩트가 포함된 비디오가 나올 수도 있습니다. 그들은 작을 수도 있지만 보기에도 흉해 보입니다.

관련 정보