0

I want to make a video using a cover image and an audio file with the audio file as the length. What's the most optimal modern way to do this with new codecs and high resolutions?

Reason why I want 4K/8K: The deployment display is an 8K panel and a lower resolution yields sub-par experience.

Here's the command I tried: ffmpeg -r 0.01 -loop 1 -i image.jpg -i audio.mp3 -c:v hevc_toolbox -c:a aac -b:a 196k -pix_fmt yuv420p -shortest out.mp4

But the output was inconsistent and usually 1.5-2x the length of the audio file even with -shortest

Relevant Past Research:

  1. ffmpeg has a long-standing still-open bug about this issue where it can't approximate timing of the output correctly: trac.ffmpeg.org/ticket/5456

  2. https://superuser.com/questions/1041816/combine-one-image-one-audio-file-to-make-one-video-using-ffmpeg but it doesn't cover it

And a lot of Reddit posts with h264/1080p instructions that were not fully applicable here.

ffmpeg version 6.1.1 Copyright (c) 2000-2023 the FFmpeg developers built with Apple clang version 15.0.0 (clang-1500.1.0.2.5)

4
  • What was the original full command you tried? And which ffmpeg version?
    – Gyan
    Feb 21 at 4:33
  • added the command Feb 21 at 16:49
  • And version? ...
    – Gyan
    Feb 22 at 4:27
  • oops, added version Feb 27 at 6:48

1 Answer 1

0

Directly converting mp3 was yielding incorrect times. So pre-converting to aac and then doing a loss-less copy to mp4 fixed it. I currently use the following:

for i in *.mp3;
do (
  ffmpeg -i "$i" -b:a 256k "${i%.*}.aac";
  ffmpeg -r 0.01 -i image.jpg
         -i "${i%.*}.aac" -c:a copy -shortest -max_interleave_delta 500M
         -c:v libx265 -x265-params lossless=1 -pix_fmt yuvj420p -vf "loop=-1:1"
         -movflags faststart "${i%.*}.mp4");
done
  • -r 0.01: Sets a very low framerate (0.01 frames per second), making it essentially a static image video. This feels so hacky, I'd love to get your input if there's a better/proper way to do this!

  • -i image.jpg: Specifies the input image file that has resolution of 7680x4320.

  • -i "${i%.*}.aac": Takes the previously generated AAC audio file.

  • -c:a copy: Copies the audio stream without re-encoding (saving time).

  • -shortest: Makes the output video end when the shortest input (image or audio) ends.

  • -max_interleave_delta 500M: Improves compatibility for streaming by limiting audio/video gaps.

  • -c:v libx265: Uses the x265 (HEVC) video encoder for efficient compression. I wanted to use hevc_toolbox since I'm on an arm64 MacOS machine but it doesn't seem to support similar parameters. If you know a hack to use that for still images, please share!

  • -x265-params lossless=1: Sets x265 encoding to lossless mode for high-quality output.

  • -pix_fmt yuvj420p: Sets a common color format for compatibility. Even though , using [this format fixes/avoids][1] the deprecated pixel format used, make sure you did set range correctly` warning that you get.

  • -vf "loop=-1:1": Loops the image indefinitely (-1 means unlimited, size is 1 frame).

  • -movflags faststart: Optimizes the video file for web streaming.

  • "${i%.*}.mp4": Replaces the ".mp3" extension with ".mp4", creating an MP4 video file as output.

The resultant file works in Youtube, but doesn't work well in Infuse, VLC, Quicktime or Finder's QuickLook. Dunno how to fix that.

Next goal is to do a royalty-free version of this with av1/vp9 and Opus. And to add subtitle files

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.