FFmpeg로 부분적으로 완료된 인코딩 재개

Sep 26 2020

요약

부분적으로 완료된 인코딩이 주어지면 다음과 같습니다.

  • Matroska 컨테이너에서 h264를 사용하여 인코딩되었습니다.
  • 콘솔에 'q'를 입력하여 FFmpeg를 수동으로 중지하여 단축되었습니다.

... 가급적 기존 파일을 추가하여이 파일 인코딩을 재개하는 방법은 무엇입니까?

세부

경우에 따라 최대 1 주일까지 소요될 수있는 대규모 인코딩 프로젝트가 있습니다. 이상적인 상황에서 인코딩을 수행하는 컴퓨터는 중단없이 작업을 수행 할 수 있습니다. 하지만 실제 상황에서는 여러 가지 이유로 컴퓨터가 인코딩을 중지하고 종료하거나 다시 시작해야하는 경우가 있습니다. 이 때문에 중단 가능성을 예상하고 FFmpeg 자체를 사용하여 나중에 중단 된 부분을 다시 선택하여 해당 컴퓨터에서 FFmpeg를 사용하여 인코딩을보다 "방탄"하는 방법을 찾고 있습니다.

내가 지금하고있는 일

이런 일이 발생하면 인코딩 된 파일을 복구하고, 비디오 편집 소프트웨어에서 검사하고, 좋은 스 플라이 싱 지점을 찾은 다음 AviSynth를 사용하여 이전 세그먼트가 중단 된 새 세그먼트 인코딩을 시작하는 스크립트를 만듭니다. 그런 다음 다른 소프트웨어를 사용하여 기존 인코딩을 트리밍하여 스플 라이스가 매끄럽게 된 다음 FFmpeg의 demuxer를 사용하여 나중에 개별 h264 세그먼트를 완성 된 파일로 결합합니다.

이것은 더 자동화 된 솔루션이있는 경우 피하고 싶은 매우 느릴 수있는 많은 수동 작업입니다.

아이디어

분할 : 이것은 가장 유망한 솔루션처럼 보이지만 어떻게 채워야할지 잘 모르겠습니다. 이 답변 은 많은 것을 다루는 것 같습니다. FFmpeg에 대략적인 간격으로 I-Frame에서 분할 된 출력 세그먼트를 지시 할 수 있으며 나중에 다시 다중화 할 수 있습니다. 그 대답과 FFmpeg의 문서 를 보면 알지 못하는 것은 특정 세그먼트에서 다시 인코딩을 시작하는 방법입니다. FFmpeg에 각 세그먼트가 프레임 또는 타임 코드를 통해 시작해야하는 위치를 알려주는 파일을 제공하는 방법이있는 것 같지만, 목록 중간에서 시작하려면 어떻게해야합니까?

그러나이 옵션은 세그먼트를 단일 파일로 다중화해야하므로 결과 인코딩 (종종 100GB 크기)의 두 배 공간을 효과적으로 사용할 수 있어야한다는 점에서 이상적이지 않습니다. 진행중인 인코딩을 어떻게 든 깔끔하게 잘라 내고 FFmpeg가 해당 파일을 다시 열고 중단 된 부분을 계속할 수 있다면 좋을 것입니다.

가상 머신 : 다시 시작하기 전에 머신의 상태를 고정 할 수 있기 때문에 작동 할 가능성이 있지만 모든 인코딩 공간이 네트워크 연결 스토리지에 존재합니다. 가상 머신의 컨텍스트에서 작동할지 확실하지 않습니다. VM이 실제로 드라이브를 제어하지 않기 때문에 일시 중지 및 재개되었습니다.

답변

1 ZachF. Oct 02 2020 at 13:44

이 문제에 대한 "충분히 좋은"해결책을 찾았습니다. 글을 쓰는 시점에서 임의로 잘라낸 부분 인코딩을 실제로 선택하여 나머지 비디오를 정확하게 연결하는 것이 불가능 해 보이기 때문입니다. .

분할을 사용하는 솔루션

첫째, FFmpeg의 분할 기능을 사용하여 이러한 간격을 잃는 것이 허용 가능한 손실 인 일정 간격으로 세그먼트를 출력합니다. 또한 세그먼트 시작 및 종료 시간이있는 .csv 파일을 출력합니다. 이를 수행하는 예제 명령은 다음과 같습니다.

ffmpeg.exe -i .\source.avi -c:v libx264 -crf 20 -c:a aac -pix_fmt yuv420p -f segment -segment_time 30 -segment_list segments.csv -reset_timestamps 1 seg%03d.mkv

네 번째 세그먼트 (seg003.mkv)를 인코딩하는 동안 인코더를 중지하고 머신을 재설정해야한다고 가정합니다. q세그먼트를 인코딩하는 동안 FFMpeg 에 키 입력을 보내면 특정 지점에서 임의로 중지되고 해당 세그먼트가 불완전하게 유지됩니다.

중단 된 세그먼트는 효과적으로 손실되며 삭제할 수 있습니다. segment.csv 파일을 열면

seg000.mkv,0.000000,33.390000
seg001.mkv,33.390000,62.586000
seg002.mkv,62.586000,91.782000
seg003.mkv,91.782000,98.655000

이 정보를 사용하여 seg003.mkv가 소스에서 91.782 초에 시작되었음을 알 수 있습니다. 중단 한 부분을 선택하기 위해 위와 동일한 명령을 사용하여 분할 된 출력을 인코딩하고 ( -ss)를 네 번째 세그먼트의 시작 부분까지 찾고 번호 매기기 ( -segment_start_number)를 변경합니다 .

ffmpeg.exe -ss 91.782000 -i source.avi -c:v libx264 -crf 20 -c:a aac -pix_fmt yuv420p -f segment -segment_time 30 -segment_list segments2.csv -segment_start_number 3 -reset_timestamps 1 seg%03d.mkv

FFmpeg는 네 번째 세그먼트의 시작 부분에서 선택하여 seg003.mkv로 올바르게 이름을 지정합니다. 원본을 덮어 쓰지 않도록 출력 .csv 파일의 이름이 변경되었습니다. 이 새 .csv 파일은 0.00에서 시작하므로 추가 중단은 시작 지점을 찾기 위해 이전 파일에이 파일의 시간을 추가해야합니다.

마지막으로 모든 세그먼트를 연결할 준비가 되면 위키 페이지 의 예제에 설명 된대로 .ffcat 파일을 생성합니다 .

file seg000.mkv
file seg001.mkv
file seg002.mkv
file seg003.mkv
file seg004.mkv
file seg005.mkv

다음 명령을 실행하십시오.

ffmpeg.exe -f concat -i .\segments.ffcat -c copy output.mkv

이렇게하면 연결된 전체 인코딩이 출력됩니다. 이 옵션 -fflags +genpts은 질문의 연결된 답변에 언급되어 있으며 완벽한 결과를 얻기 위해 필요할 수 있지만 테스트에서 차이를 만들지 못했습니다.