FLV хранит 32-битные метки времени. Так хранится TS
ел несколько вопросов, касающихся значений PTS для видео, не начинающихся с нуля, или спрашивающих, как заставить их начинать с нуля. Я знаю, что с помощью ffmpeg я могу сделать что-то вродеffmpeg -i <video> -vf="setpts=PTS-STARTPTS" <output>
чтобы исправить подобные вещи
Однако я понимаю, что значения PTS неимеют начать с нуля. Например, если вы присоединяетесь к прямому эфиру, то, скорее всего, он продолжается уже час, а PTS уже где-то около 3600000+, но ваш видеоплеер точно отображает все просто отлично. Поэтому я ожидаю, что не будет никаких проблем, если я намеренно создаю видео со значением PTS, начиная, скажем, с текущего времени настенных часов.
Я хочу отправить живой поток, используя ffmpeg, но встроить текущее время в поток. Это может быть использовано как для расчета задержки, пока поток является живым, так и позже, чтобы определить, когда поток был первоначально передан. Из моего понимания PTS, что-то простое, как это, вероятно, должно работать:
ffmpeg -i video.flv -vf="setpts=RTCTIME" rtmp://<output>
Однако, когда я пытаюсь это сделать, ffmpeg выдает следующее:
frame= 93 fps= 20 q=-1.0 Lsize= 9434kB time=535020:39:58.70 bitrate= 0.0kbits/s speed=1.35e+11x
Обратите внимание на чрезвычайно большое значение для «времени», битрейта (0,0 кбит) и скорости (135000000000x!!!)
Сначала я подумал, что проблема может быть моей временной базой, поэтому я попробовал следующее:
ffmpeg -i video.flv -vf="settb=1/1K,setpts=RTCTIME/1K" rtmp://<output>
Это помещает все в миллисекунды (1 PTS = 1 мс), но у меня была та же проблема (большое время, нулевой битрейт и огромная скорость)
Я что-то неправильно понимаю о PTS? Разве нельзя начинать с ненулевых значений? Или я просто что-то делаю не так?
ОбновитьИзучив ответ @ Gyan, я отформатировал свою команду следующим образом:
ffmpeg -re -i video.flv -vf="settb=1/1K, setpts=(RTCTIME-RTCSTART)/1K" -output_ts_offset $(date +%s.%N) rtmp://<output>
Таким образом, значения PTS будут соответствовать «миллисекундам с момента запуска потока» и будут смещены на время начала потока (теоретически PTS = отметка времени на сервере)
Это выглядело так, как будто это было лучше:
frame= 590 fps=7.2 q=22.0 size= 25330kB time=00:01:21.71 bitrate=2539.5kbits/s dup=0 drop=1350 speed= 1x
Битрейт был теперь верным, время было точным, а скорость не была возмутительной. Тем не менее, частота кадров в секунду все еще немного снижена (исходное видео составляет 24 кадра в секунду, но оно сообщает 7,2 кадра в секунду).
Когда я попытался посмотреть поток с другого конца, видео было не синхронизировано со звуком и какое-то время воспроизводилось с удвоенной нормальной скоростью, затем видео застыло, и звук продолжался без него.
Кроме того, когда я сбросил поток в файл (ffmpeg -i rtmp://<output> dump.mp4
) и посмотрите на временные метки PTS с помощью ffprobe (ffprobe -show_entries packet=codec_type,pts dump.mp4 | grep "video" -B 1 -A 2
) метки времени вообще не показывают время сервера:
...
--
[PACKET]
codec_type=video
pts=131072
[/PACKET]
[PACKET]
codec_type=video
pts=130048
[/PACKET]
--
[PACKET]
codec_type=video
pts=129536
[/PACKET]
[PACKET]
codec_type=video
pts=130560
[/PACKET]
--
[PACKET]
codec_type=video
pts=131584
[/PACKET]
Проблема только в несовместимости с RTMP?
Обновление 2Я удалил видеофильтр и теперь кодирую так:
ffmpeg -re -i video.flv -output_ts_offset $(date +%s.%N) rtmp://<output>
Это кодировка правильно:
frame= 910 fps= 23 q=25.0 size= 12027kB time=00:00:38.97 bitrate=2528.2kbits/s speed=0.981x
Чтобы убедиться, что значения PTS верны, я вывожу вывод в файл примерно так:
ffmpeg -i rtmp://<output> -copyts -write_tmcd 0 dump.mp4
Я пытался сохранить его какdump.flv
(поскольку это RTMP), однако, это выдало ошибку:
[flv @ 0x5600f24b4620] Audio codec mp3 not compatible with flv
Это немного странно, поскольку видео не закодировано в формате mp3 (это speex) - но что угодно.
При выводе этого файла постоянно появляется следующая ошибка:
frame= 1 fps=0.0 q=0.0 size= 0kB time=00:00:09.21 bitrate= 0.0kbits/s dup=0 dr
43090023 frame duplication too large, skipping
43090027 frame duplication too large, skipping
Last message repeated 3 times
43090031 frame duplication too large, skipping
Last message repeated 3 times
43090035 frame duplication too large, skipping
Воспроизведение полученного видео в VLC воспроизводит аудиопоток, но не отображает видео. Затем я пытаюсь исследовать это видео сffprobe
чтобы посмотреть значения PTS видео:
ffprobe -show_entries packet=codec_type,pts dump.mp4 | grep "video" -B 1 -A 2
Это возвращает только один видеокадр, у которого PTS не большой, как я ожидал:
[PACKET]
codec_type=video
pts=1020
[/PACKET]
Это было удивительно трудной задачей