Search code examples
ffmpeghttp-live-streaming

ffmpeg keyframe control on single image + audio


I have scoured every related StackOverflow question I can find and none of them solved the issue, apologies in advance if I missed the one that would have worked.

The application I am working on converts a video or audio file to an mp4, and later on the server to an hls playlist. I just implemented audio and I wanted a background image. After reading through various options on StackOverflow I settled on the following args:

-y -i "C:\path\ExternalAudioBackground.png" -i "C:\path\Audio.mp3" -vf scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:-1:-1:color=black -c:a copy -vcodec libx264 -pix_fmt yuv420p "C:\path\external_media_file.mp4"

This set of args was chosen because it is instantaneous due to -c:a copy as well as constraints to ensure all videos have the same aspect ratio and encoding.

The issue is when converting this to an hls stream the stream fails to play (in video.js player, and also vlc) with the message :

VIDEOJS: WARN: Segment with index 0 from playlist 0-https://domain/video.m3u8 has a duration of 464.96 when the reported duration is 0.04 and the target duration is 0.04. For HLS content, a duration over the target duration may result in playback issues. See the HLS specification section on EXT-X-TARGETDURATION for more details: https://datatracker.ietf.org/doc/html/draft-pantos-http-live-streaming-23#section-4.3.3.1 https://datatracker.ietf.org/doc/html/draft-pantos-http-live-streaming-23#section-4.3.3.1

Adding -loop 1 to the start increases the processing time from milliseconds to minutes, but produces a working file

Adding -r 1 and -loop 1 takes longer to process than without -r (!?)

Adding -stream_loop 116 (116 is the length of the audio in seconds divided by 4, the desired hls segment size) before the image input loops the first 4 seconds of the audio over and over

adding -g 96 (96 is the fps * 4)

In case relevant, the hls encoding arguments look like this:

-safe 0 -f concat -i listOfFiles.txt -c:a aac -ar 48000 -b:a 128k -vcodec copy -crf 20 -g 48 -keyint_min 48 -sc_threshold 0 -b:v 2500k -maxrate 2675k -bufsize 3750k -hls_time 4 -hls_playlist_type vod  -hls_segment_filename segment-%03d.ts result.m3u8

listOfFiles.txt always contains only one file in the case being discussed.

How can I achieve this with the minimum processing time but still have the file convertable to HLS?


Solution

  • Thanks to @Gyan for solving this in comments:

    Add -loop 1 -framerate 0.5 before the image input and -intra after libx264

    Add -shortest -fflags +shortest -max_interleave_delta 100M