ffmpeg로 비디오를자를 때 키 프레임 시간 거리 보상


1

내 요구 사항은 정확히 (몇 프레임 위로 / 아래로) 플라이 MP4 (h264 + aac) https 비디오 스트림을 잘라내는 것입니다. 휴대 전화에서 ffmpeg를 가장 빨리 할 수 ​​있습니다 - 필요한 경우 나쁜 압축 (더 큰 출력 파일) 더 큰 절단 속도. 현재이 명령으로 비디오를 자르고 있습니다 :

ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 00:00:10.000 -c:a copy -c:v copy out.mp4

이 방법 (비트 스트림 복사)은 매우 빠르며 (10 초 길이의 비디오를 잘 처리 할 수있는 좋은 네트워크에서는 1 초 미만) 비디오를 정확하게 자르지 않습니다. 비디오는 부정확 한 키 프레임에서 잘려나갑니다.

그래서 내 생각은 비디오 프레임을 재생하기 전에 동영상에서이 부정확성 (키 프레임으로부터의 거리)을 보상하는 것입니다.

delta = start_time - first_key_frame_timestamp_before_start_time

델타를 계산하려면 시작 시간 전에 첫 번째 키 프레임의 타임 스탬프를 얻는 매우 빠른 방법이 필요합니다. 나는 본 적이 우편 start_time 이전에 첫 번째 키 프레임의 타임 스탬프를 얻는 방법에 대해 설명하지만이 방법은 비디오의 중간이라고 할 수있는이 작업이 오래 걸리기 때문에 오랜 (2 시간 +) 비디오에는 실용적이지 않습니다. 나는 이런 것을 필요로 할 것이다 :

ffmpeg -ss 01:30:06.000 -i https://domain/in.mp4 -t 2 -show_frames > frame_meta.txt

또한 다음 명령을 사용하여 비디오를 다시 인코딩 (2 시간 길이의 비디오, 비디오 중간에 10 초 길이의 비디오 잘라 내기)하여 정확한 절단을 시도했습니다.

ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 10 out.mp4

그러나 두 번째 비트 스트림 복사 명령보다 짧아서 모바일에서 길게 (~ 16 초) 걸립니다. 유용한 힌트 또는 솔루션 Thx.

편집 1 :

ExoPlayer (Android 멀티미디어 플레이어) 내부 클래스를 사용하여 delta를 계산하고 start_time 이전에 첫 번째 keyFrame의 타임 스탬프를 얻었습니다.이 방법은 500ms (매우 짧은 비디오)에서 최대 1500ms (매우 긴 비디오의 경우)까지 매우 빠릅니다. 근본적으로이 방법은 원격 mp4 스트림의 meta_headers (moov 아톰)를 구문 분석하여 start_time을 자르기 전에 keyFrame의 적절한 timeStamp를 찾은 것을 기반으로합니다. 이제 새로운 문제는 비디오가 잘리는 경우 발생합니다.

ffmpeg -ss [start_time] -i https://domain/in.mp4 -t 00:00:10.000 -c:a copy -c:v copy out.mp4

편집 목록 아톰은 다음에서 이해할 수있는 메타 헤더에 추가됩니다. ffmpeg bitStream copy 명령으로 수행되는 부정확 한 비디오 커팅을 보상하기 위해 플레이어에게 델타 시간 오프셋으로 재생을 시작하라고 알려주는 게시물입니다. 그러나 Android에서 사용하는 플레이어는 동영상 시작 부분부터 정상적으로 재생되기 시작하거나 오디오가 재생되는 동안 잠시 동안 일부 프레임에서 정지되어 정상적으로 재생되기 때문에 편집 목록 재생을 지원하지 않습니다.

이전에 계산 된 델타를 찾은 다음 잘라낸 비디오에서 재생을 시작하려고하면 올바른 프레임 (예 : 델타 = 1 381ms, 실제 / 작동중인 델타 = 444ms)에 위치하지 않아 정확하지 않은 절단을 보상하는 계획이 작동하지 않습니다. (. 델타를 올바르게 계산했는지 스스로 묻는다면 IsoViewer (mp4 컨테이너 아톰 파서) 및 Avidemux로 프레임을 단계별로보고 time_stamp / frame_type 값 쌍을 조사하여 mannualy ...


나는 생각한다. 여전히 가장 빠른 방법입니다.
Gyan

좋은 팁 Thx, 나는 당신의 대답을 보았다. 그러나 STSS 아톰의 어떤 키 프레임 인덱스가 start_time 이전의 키 프레임 인덱스인지는 어떻게 알 수 있습니까? 그 원자는 키 프레임의 인덱스만을 보유하기 때문입니다 - 키 프레임은 {{keyframe_index, time_stamp}, {} ...와 같은 키 - 값 쌍이었습니다. 그것은 아주 쉬울 것입니까?
xyman

KF의 인덱스는 시간 x FPS이므로 25fps 비디오에서 0x30은 1.96 초의 시간을 나타냅니다. 이것은 일정한 프레임 속도 비디오를 가정합니다.
Gyan

오, 그렇군, 완벽 해. 하지만 다른 문제는 mp4parser에 https 스트림을 제공하는 방법 일 것입니다. 왜냐하면 mp4parser에 익숙하기 때문에 로컬 전체 길이 비디오 파일로만 작업하기 때문입니까? 일을하기 위해 모든 종류의 해킹이 가능합니다.
xyman

@Mulvya 안녕하세요, 저는 ExoPlayer (안드로이드 비디오 플레이어) 내부 클래스로 moov 원자를 빠르게 파싱하고 커팅 시간 전에 첫 번째 keyFrame의 타임 스탬프를 가져 왔습니다. 지금은 / v 코덱 복사 ffmpeg 명령으로 비디오를자를 때 다른 문제가 있습니다. 편집 목록 아톰이 만들어져서 부정확 한 비디오 자르기를 보정하기 위해 거기에 놓여 있습니다. 잘못하면 수정하십시오. 그러나 편집 목록이 존재하면 부정확 한 편집을 보상 할 필요가 없으며 비디오 플레이어는 편집 목록에 정의 된 지점에서 재생해야합니까? 하지만 대부분의 플레이어는 편집 목록을 지원하지 않습니다 ...
xyman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.