iOS용으로 트랜스코딩된 MP4(HEVC/x265/mov_text)와 SRT 자막을 병합하는 데 문제가 있습니다. "pts에 값이 없습니다." 및 "mov/mp4 형식의 범위를 벗어났습니다."

iOS용으로 트랜스코딩된 MP4(HEVC/x265/mov_text)와 SRT 자막을 병합하는 데 문제가 있습니다. "pts에 값이 없습니다." 및 "mov/mp4 형식의 범위를 벗어났습니다."

HEVC(x265) 비디오 인코딩을 사용하여 MKV 비디오를 MP4로 트랜스코딩하여 iOS와 모두 호환되도록 파일을 더 작게 만드는 방법을 배웠습니다. 그러나 프로세스가 훌륭하고 낮은 파일 크기로 압축이 훌륭하지만 자막을 하나의 특정 비디오로 병합하려고 하면 결과 MP4 비디오에서 FFmpeg에서 다음과 같은 오류 더미가 발생합니다.

[mp4 @ 0x7facb9002000] pts has no value
[mp4 @ 0x7facb9002000] Application provided duration: 3152805999 / timestamp: 3154741000 is out of range for mov/mp4 format

Homebrew를 통해 설치된 FFmpeg 4.2.1과 함께 macOS Mojave(10.15.2)를 사용하고 있는데, 다운로드해도 문제가 지속됩니다.야간 빌드(ffmpeg-4.2.1-macos64-static, 20191215-9fe0790) Homebrew 설치 버전 대신 해당 바이너리를 사용하세요.

문제는 과거에 x264 비디오 및 AAC 오디오가 포함된 MP4로 성공적으로 변환했으며 SRT 자막도 문제 없이 결과 파일에 병합할 수 있었던 이 비디오가 있다는 것입니다. 그러나 오늘 동일한 소스에서 HEVC(x265) 비디오를 사용하여 MP4를 생성하면 "pts에 값이 없습니다" 및 "mov/mp4 형식의 범위를 벗어났습니다" 오류와 함께 SRT 자막 병합이 실패합니다.

다음은 MKV 소스에서 HEVC(x265) MP4 비디오를 생성하는 데 사용하는 명령입니다.

ffmpeg -i input.mkv \
       -map_metadata -1 \
       -vf scale=-1:720 \
       -c:v libx265 -crf 20 -c:a aac -b:a 128k \
       -threads 4 \
       -tag:v hvc1 -sn \
       -map 0:0 -map 0:1 output_hevc.mp4 \
       ;

그리고 이것은 과거에 다시 인코딩하지 않고 SRT 자막을 기존 MP4에 병합하기 위해 성공적으로 사용한 명령입니다.

ffmpeg -i output_hevc.mp4 \
       -i input.srt \
       -c:v copy -c:a copy \
       -c:s mov_text -metadata:s:s:0 language=eng \
       output_final.mp4 \
       ;

내 생각에 문제는 비디오의 약 50%에 자막이 없다는 것입니다. 영상의 두 번째 50%에만 자막이 필요합니다.

문제의 영상 길이는 약 2시간 정도입니다. 그리고 처음 50분 정도는 영어 자막이 필요하지 않습니다. 그런데 50분 정도 지나면 자막이 나오거든요.

따라서 SRT의 자막은 다음과 같이 시작됩니다.

1
00:52:33,123 --> 00:52:50,123
It was a dark and stormy night…

하지만 위의 FFmpeg 명령을 실행하면 출력은 다음과 같습니다. 예의 목적에 따라 약간 퍼지되었습니다.

Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
  Stream #1:0 -> #0:2 (subrip (srt) -> mov_text (native))
Press [q] to stop, [?] for help
frame=25560 fps=0.0 q=-1.0 size=  304640kB time=00:52:00.00 bitrate= 791.7kbits/frame=50730 fps=50726 q=-1.0 size=  681984kB time=time=00:52:00.00 bitrate=1772.4kbit[mp4 @ 0x7facb9002000] Application provided duration: 3152137000 / timestamp: 3152137000 is out of range for mov/mp4 format
[mp4 @ 0x7facb9002000] pts has no value
[mp4 @ 0x7facb9002000] Application provided duration: 3152805999 / timestamp: 3154741000 is out of range for mov/mp4 format
[mp4 @ 0x7facb9002000] pts has no value
[mp4 @ 0x7facb9002000] Application provided duration: 3153246998 / timestamp: 3156809000 is out of range for mov/mp4 format
[mp4 @ 0x7facb9002000] pts has no value
[mp4 @ 0x7facb9002000] Application provided duration: 3154051997 / timestamp: 3159013000 is out of range for mov/mp4 format
[mp4 @ 0x7facb9002000] pts has no value
[mp4 @ 0x7facb9002000] Application provided duration: 3155556996 / timestamp: 3163817000 is out of range for mov/mp4 format

그리고 비슷한 메시지가 엄청나게 많이 있습니다. 짜잔! 병합이 종료되고 자막을 볼 수 없습니다.

이게 나를 미치게 만들고 있어! 동일한 명령을 사용하지만 자막이 들어오는 지점 근처에서 시작하는 검색 시간을 지정하면 실제로 필요한 비디오의 50%에서 자막이 표시됩니다.

ffmpeg -I output_hevc.mp4 \
       -i input.srt \
       -c:v copy -c:a copy \
       -c:s mov_text -metadata:s:s:0 language=eng \
       -ss 3120 \
       output_final.mp4 \
       ;

하지만 당연히 영상의 50% 이상이 필요합니다. 젠장, 방금 이 명령을 시도해 보기도 했습니다. 검색 값을 1005초 이상으로 설정하면 자막을 MP4와 병합할 수 있습니다.

ffmpeg -i output_hevc.mp4 \
       -i input.srt \
       -c:v copy -c:a copy \
       -c:s mov_text -metadata:s:s:0 language=eng \
       -ss 1005 \
       output_final.mp4 \
       ;

하지만 이 맥락에서 16.75분(1005초)이 그토록 마법적인 것은 무엇일까요?

비디오의 두 번째 50%에만 자막이 표시되는 시간만 선택하고 전체 비디오를 병합하는 명령을 실행하는 경우에는 자막이 병합되지 않는 이유는 무엇입니까?

FWIW, 유사한 명령을 실행하여 비디오의 MKV를 생성하면 모든 것이 정상입니다!

ffmpeg -i output_hevc.mp4 \
       -i input.srt \
       -c:v copy -c:a copy -c:s copy \
       output.mkv \
       ;

어떻게 든 이러한 병합으로 인해 mov_text프로세스가 실패한 것 같습니다.

그리고 다음과 같이 파일 시작 부분에 가짜 자막을 추가하면:

0
00:00:00,000 --> 00:16:75,000
Foo!

1
00:52:33,123 --> 00:52:50,123
It was a dark and stormy night…

모든 것이 원하는 대로 작동합니다! "Foo!"라는 단어를 제외하고. 영상의 50% 정도 나옵니다. 분명히 이상적이지는 않습니다.

이 문제를 해결할 방법이 있나요? 이것은 FFmpeg 버그입니까, 아니면 자막이 병합되는 HEVC(x265) 비디오의 문제입니까?

답변1

비디오 시작 부분부터 자막이 시작되는 위치까지의 SRT 파일 시작 부분에 가짜 자막을 추가하는 것처럼 보이며 이 문제가 해결되었습니다.

이 솔루션은 분명히 "해킹"이지만 작동합니다.

SRT 파일의 시작 부분에 가짜 자막을 추가하려는 내 아이디어를 바탕으로 SRT 자막이 있다는 것을 깨달았습니다.SRT 사양— HTML 태그를 허용합니다. 다음 가짜 자막을 추가했는데 모두 작동한다는 것을 알고 있습니다!

0
00:00:00,000 --> 00:16:75,000
<b></b>

1
00:52:33,123 --> 00:52:50,123
It was a dark and stormy night…

그게 다야! 빈 굵은 태그를 추가하기만 하면 모든 기능이 작동하고 자막이 병합됩니다...


그러나 처음에 언급했듯이 이것은 분명히 해킹이며 FFmpeg에 대해 더 많이 알고 있는 다른 사람들로부터 더 많은 의견을 듣고 싶습니다. 나는 이 문제 중 어느 것도 원하는 동작을 반영하지 않는다고 가정할 수 있으며 이와 같은 경우를 처리하는 더 우아한 방법이 있어야 합니다. 아니면 버그(기능이 아님)이므로 보고해야 합니까?

답변2

나는 작업 중인 미디어 파일에 이와 똑같은 문제가 있었고, 하루 중 더 많은 시간을 다른 명령을 시도하고 pts를 재구축하는 다른 방법을 시도했지만 결국 이 게시물을 우연히 발견했습니다. 안타깝게도 여기서 제안된 해결 방법은 나에게 효과가 없었습니다.

저는 gyan.dev에서 Windows용으로 컴파일한 바이너리를 사용하여 Windows 11에서 실행하고 있지만 ubuntu를 실행하고 apt를 통해 설치하는 WSL(Linux용 Windows 하위 시스템)을 통해 동일한 명령을 시도했습니다.

빈 태그를 삽입할 때 동일한 오류가 계속 발생했습니다.

0
00:00:00,000 --> 00:18:00,000
<b></b>

1
00:43:21,472 --> 00:43:24,933
Mysterious translated text here

[mp4 @ 0000023630f5cf80] Packet duration: 2601472000 / dts: 2601472000 is out of range
[mp4 @ 0000023630f5cf80] pts has no value
[mp4 @ 0000023630f5cf80] Packet duration: 2601681999 / dts: 2605143000 is out of range
[mp4 @ 0000023630f5cf80] pts has no value
[mp4 @ 0000023630f5cf80] Packet duration: 2602474998 / dts: 2608605000 is out of range
[mp4 @ 0000023630f5cf80] pts has no value
[mp4 @ 0000023630f5cf80] Packet duration: 2603642997 / dts: 2611441000 is out of range
[mp4 @ 0000023630f5cf80] pts has no value

대신 단일 마침표와 같이 표시되는 단일 문자를 삽입하면 srt 파일이 문제 없이 병합됩니다. 물론 비디오의 처음 40분 동안 화면에 마침표가 표시됩니다.

0
00:00:00,000 --> 00:18:00,000
.

1
00:43:21,472 --> 00:43:24,933
Mysterious translated text here

굵은 태그, 기울임꼴 태그 및 인식되지 않는 단락 태그까지 생각할 수 있는 다른 태그를 사용해 보았습니다. 빈 태그는 보관 시간을 트리거하지 않으며 'pts에는 값이 없습니다' 오류가 발생합니다.

필사적으로 나는 매우 짧은 지속 시간으로 2분 간격으로 10개의 항목을 추가하여 질보다 양의 접근 방식을 사용하기로 결정했습니다. 그래서 견고한 가시 마침표 문자 대신 간헐적인 문자를 갖게 되었고 이것이 효과가 있었습니다. 그래서 변덕스럽게 처음 10개 항목의 시작 시간과 종료 시간을 동일하게 설정하려고 시도했는데 그 결과 마침표 문자가 숨겨지고 자막이 오류 없이 병합되었습니다.

1
00:02:00,000 --> 00:02:00,000
.

2
00:04:00,000 --> 00:04:00,000
.

3
00:06:00,000 --> 00:06:00,000
.

4
00:08:00,000 --> 00:08:00,000
.

5
00:10:00,000 --> 00:10:00,000
.

6
00:12:00,000 --> 00:12:00,000
.

7
00:14:00,000 --> 00:14:00,000
.

8
00:16:00,000 --> 00:16:00,000
.

9
00:18:00,000 --> 00:18:00,000
.

10
00:20:01,000 --> 00:20:01,000
.

11
00:43:21,472 --> 00:43:24,933
Mysterious translated text here

여기의 원본 게시물과 마찬가지로 이것은 해킹된 해결 방법이며 적절한 솔루션은 아니지만 여기의 원본 게시물과 마찬가지로 적절한 솔루션을 찾을 수 없습니다. 이 문제가 있고 저처럼 이 게시물을 우연히 발견한 다른 사람에게 이것이 도움이 되기를 바랍니다.

손으로 증가시켜야 하는 큰 srt가 있는 경우 GPT에서 이 작은 Python 스크립트를 작성하도록 했습니다. (직접 작성할 수도 있었지만 이 시점에서 이 문제와의 싸움은 거의 끝났고 다음과 같이 생각했습니다. GPT가 처리할 수 있을 만큼 간단함)

def add_entries_to_srt(existing_file_path, new_file_path, num_entries=10, duration=0.1, buffer_time=120):
    with open(existing_file_path, 'r', encoding='utf-8') as existing_file:
        existing_content = existing_file.read()

    # Parse existing entries
    entries = existing_content.strip().split('\n\n')
    existing_entries_count = len(entries)

    # Generate new entries
    new_entries = []
    for i in range(1, num_entries + 1):
        start_time = i * (duration + buffer_time)
        end_time = start_time + duration
        entry_text = f"{i}\n{format_time(start_time)} --> {format_time(end_time)}\n<i>.</i>"
        new_entries.append(entry_text)

    # Increment entry numbers of existing entries
    for i in range(existing_entries_count):
        entry_lines = entries[i].split('\n')
        entry_number = int(entry_lines[0])
        entry_lines[0] = str(entry_number + num_entries)
        entries[i] = '\n'.join(entry_lines)

    # Combine new and existing entries
    combined_entries = '\n\n'.join(new_entries + entries)

    # Write to the new file
    with open(new_file_path, 'w', encoding='utf-8') as new_file:
        new_file.write(combined_entries)

def format_time(seconds):
    minutes, seconds = divmod(seconds, 60)
    hours, minutes = divmod(minutes, 60)
    return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d},000"

# Replace 'existing_subtitle.srt' with your actual file path
existing_file_path = r'C:\Temp\ffmpeg\Subtitles.srt'
new_file_path = r'C:\Temp\ffmpeg\Subtitles.EDIT.srt'

add_entries_to_srt(existing_file_path, new_file_path)

편집하다: 플레이어에 따라 처음 10개 항목의 시작 및 종료 시간을 설정하면 해당 기간이 숨겨지거나 5초 동안 표시되는 결과가 나타나는 것으로 나타났습니다. 1밀리초의 오프셋을 설정하는 것이 기간을 숨기는 데 훨씬 더 안정적인 것으로 보입니다.

1
00:02:00,000 --> 00:02:00,001
.

2
00:04:00,000 --> 00:04:00,001
.

3
00:06:00,000 --> 00:06:00,001
.

4
00:08:00,000 --> 00:08:00,001
.

5
00:10:00,000 --> 00:10:00,001
.

6
00:12:00,000 --> 00:12:00,001
.

7
00:14:00,000 --> 00:14:00,001
.

8
00:16:00,000 --> 00:16:00,001
.

9
00:18:00,000 --> 00:18:00,001
.

10
00:20:01,000 --> 00:20:01,001
.

11
00:43:21,472 --> 00:43:24,933
Mysterious translated text here

관련 정보