ffmpeg 오디오 싱크 문제

최근 게임 플레이 영상 녹화를 자주 하면서 mp4 영상을 쉽게 자르는 방법을 찾아보니 ffmpeg의 기본 기능을 이용하는 것이 제일 간편하다는 사실을 알게 되었습니다. 그리고 구글 검색을 통해 한 블로그에서 아래의 명령줄을 발견하게 되었습니다. 참고로 이건 windows powershell에서 쓰는 명령어이고, cmd에서는 처음 부분이 ./ffmpeg.exe가 됩니다.

.\ffmpeg.exe -i input_file -ss starting_point -t duration -vcodec copy -acodec copy output_file
Code language: CSS (css)

이렇게 하면 입력된 파일에서 시작 위치로부터 지정된 시간 동안의 영상을 출력 파일로 저장할 수 있습니다. 그런데 가끔 오디오 싱크가 안맞게 되는 현상이 벌어집니다. 해당 영상을 하나 보여드리려고 하였더니, 유튜브에서는 정상으로 나오더군요. 그래서 오디오 싱크가 안맞는 영상을 여러 플레이어를 통해 테스트해보니 어떤 경우에는 안맞고, 어떤 경우에는 잘 맞는 현상이 벌어졌습니다. 그래도 여전히 찝찝합니다. 일단 오디오가 어긋난 파일의 영상을 재녹화하여 업로드하였습니다.

오디오가 싱크가 안맞는 근본적인 이유를 알아보았더니 그 이유는 바로 명령어 체계를 잘못 이해하고 있었기 때문입니다. -ss 옵션은 입력과 출력 파일 모두에 적용할 수 있는데, 앞서 적은 명령줄은 출력 파일에 대해서 지정된 옵션이었던 것이죠. ffmpeg documentation에 보면 아래와 같이 나와 있습니다. 입력, 출력 파일에 적용시에 -ss옵션이 미묘하게 다르게 작용합니다. [링크]

-ss position (input/output)

When used as an input option (before -i), seeks in this input file to position. Note that in most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and -accurate_seek is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when -noaccurate_seek is used, it will be preserved.

When used as an output option (before an output url), decodes but discards input until the timestamps reach position.

입력 파일 기준으로 설정을 하여야 오디오 싱크 문제가 발생하지 않는다는 것을 발견하였고, 그 경우에 올바른 명령줄은 다음과 같아야 합니다. [링크]

.\ffmpeg.exe -ss starting_point -i input_file -t duration -vcodec copy -acodec copy output_file
Code language: CSS (css)

이렇게 만들어진 결과물을 다시 한 번 확인해 보면 이번에는 문제가 발생하지 않는다는 것을 알 수 있습니다.

특이하게도 영상이 짧거나, 어떤 경우에는 오디오가 잘 맞는 것처럼 보이지만 사실은 mp4 출력 파일에서의 seek 포인트가 우연히 맞거나 가까워서일 뿐이고 정상적인 결과물을 언제나 원한다면 후자와 같이 옵션을 입력 파일에 주는 것이 맞습니다.

12 comments

    1. 오! 축하드립니다. 이 문제를 똑같이 겪는 분이 있을 거라고는 생각도 못했는데, 글을 쓰길 잘했다는 생각이 들었습니다. 🙂

  1. 안녕하세요. 일단 좋은 정보를 올려주신 것에 대하여 감사드립니다.
    그런데 제가 읽어봐도 그리고 아무렇게나 넣어봐도 잘 모르겠습니다.

    어디에 저 명령어를 복사해서 넣어야 하는지 알려주실 수 있는지요.
    저 옵션을 어떻게 설정하는 걸까요?

    부탁드리겠습니다. (__ ) 꾸벅

    1. ffmpeg를 커맨드로 사용할 때에 쓰는 방법이고요, 빨간색으로 칠해둔 부분을 본인의 설정에 맞게 변경해야 합니다. 앞에 달린 검은 부분이 옵션이고요.

  2. 안녕하세요
    -ss를 앞부분에 넣으니까 초로 막 600초 이렇게 해버리면 그냥 바로 당장 스타트가 되어버리네요

    -ss를 뒤에 넣었을때는 600초도 다 세어서 하는데

    장시간으로 하면 되는거같기도 한데 장시간으로 해도 -ss를 앞부분에 넣으면 오류가 뜰떄가 많고

    뒤에 넣으면 오류가 안뜨네요 뭐가 문제인지 모르겠어요 ㅠ

    1. 제가 쓰던게 옛날 버전일 수도 있는데, -ss 옵션으로 600초, 10분을 주려면 -ss 00:10:00 으로 줘야했던 것 같습니다. 그러면 영상을 600초 지점부터 자르기 시작한다는 뜻입니다. 이 시점을 기준으로 600초라면 -t 옵션을 사용하셔야 합니다.

    2. 그게 저도 -ss 다음에 600으로 적거나 00:10:00 둘다 줘봤는데 둘다 그냥 무시하고 스타트 끊어버리네요 원래 -ss 랑 그 뒤에 -t 를 즐겨써와서 익숙한 명령문인데 -ss를 -i 앞으로 당겨오니까 처음엔 하는척하더니 막 오류 뜨고 녹화도 안되고 그래서 다시 -ss를 뒤에 넣으면서 사용해오다가 최근에 다시 -ss를 앞에 당겼떠니 이제는 그냥 몇초를 적던간에 그냥 무시하고 스타트를 해버립니다..

      아 참고로 이게…. 저는 -i 뒤에 주소가 파일주소가 아니라 스트리밍 m3u8 입니다
      그래서 제가 원하는건 어느 특정파일에서 몇초 뒤부터 -t 까지 시간동안 끊는게 아니라
      딱 -ss 한 시간 예를 들어 600초라고 친다면 제가 이 명령문을 엔터 친 시점부터 600초뒤부터 -t까지 녹화를 하는것입니다. m3u8 스트리밍 파일은 무한대로 계속 segment 파일이 나오기때문에
      무슨 특정파일 하나를 시작시점부터 어느지점까지 끊는게 아니어서
      -ss를 앞으로 땡기면 그냥 무시하고 스타트를 해버리네요 …
      제가 막 실시간으로 녹화를 해서 A채널에서 3시부터 5시까지 녹화 B채널에서 4시부터 5시까지 녹화 C채널에서 방송되는 화면의 2시부터 4시까지 녹화 D채널에서 5시부터 8시까지 녹화 막 이런식으로 여러개 채널의 스트리밍 m3u8을 동시에 -ss와 -t를 끊어버리면 예를들어 D채널에서 5시부터 8시까지여서 5시까지는 스트리밍 segment 파일을 불러들일 필요도 없는데도 계속 segment파일을 읽어가면서 5시까지 녹화는 안하다가 5시부터 8시까지 녹화를 시킵니다. 예를들어 한시간 뒤가 5시다고 치면 -ss 3600 하면 1시간뒤부터 실제로 녹화를 해서 -t로 3시간을 초로 지정해놓으면 됩니다. 그런데 문제는 명령문을 친 시점부터 1시간까지는 이렇게 segment를 일일이 계속 불러들일 필요가없어서 그냥 -ss를 앞으로 땡겨서 주소를 불러오지말고 그냥 시간만 3600초 세고 있다가 3600초부터 -t까지 시점까지 스트리밍 파일을 불러들여서 녹화를 했으면 하는것입니다
      이게 제가 여러개 채널을 ffmpeg 로 -ss 세팅해놓고 밖에 나갔다오면 불필요하게 스트리밍 파일을 제가 녹화할 필요가 없는 앞부분도 다 불러들여서 실제로 그 시간에 다른채널 녹화를 하고있는 ffmpeg파일의 스트리밍 세그먼트 파일 불러오는걸 방해해서 녹화가 중간중간에 segment파일을 놓쳐서 끊겨버리더라고요. 차라리 2시부터 4시, 3시부터 5시 서로 각각 다른 채널에서 그 필요한 시간에만 세그먼트 파일을 불러들이면 서로 방해하는거 없을텐데 여러개 채널이 서로 다른 시점에 녹화를 해야함에도 여러개의 ffmpeg가 동시에 일을 하니까 결국 segment파일을 잃어버리는 일이 자주 생깁니다 ㅠ 이렇게 스트리밍파일을 예를 들어 600초 이후부터 로딩해서 -t까지 녹화하려면 어떻게 설정을 해야할까요?

      너무 글이 심하게 길어서 죄송합니다 ㅠㅠ
      오늘도 좋은밤 보내세요 ^^

Leave a Reply

Your email address will not be published. Required fields are marked *