0

I've been working on a service that downloads a number of images, saves them to disk, and then uses ffmpeg to create an animation (gif or mp4). This can be fairly intensive in terms of memory and CPU usage.

Are there any methods that would allow me to dynamically append and encode a new image to the animation as they're ready, rather than having to read all of the images at the end and generate the animation at the end?

  • Didn't you post this at SU few days back? I asked you a couple of Qs: does file size matter? Will you be appending exactly one image, or multiple? – Gyan Aug 18 '17 at 5:03
  • Hey @Mulvya. Nah that was a bit of a different question. The application process as it is now is that the app downloads a variety of sub images and combines them in memory into a single frame. That gets saved out as a png. When all the frames have been generated, a child process is launched that starts ffmpeg with encoding arguments to generate the final animation (MP4 or gif). The idea I'm exploring now is if it's possible to feed each image into an ongoing encoding process rather than waiting until all frames have been retrieved. – Geuis Aug 18 '17 at 5:45
  • So, you wish to keep the ffmpeg process running, or is it ok to generate a MP4 which then gets appended to? – Gyan Aug 18 '17 at 6:55
  • @Mulvya I'm not sure which approach would be better, so your guidance would be very helpful. My concern about appending to a MP4 is that its going to re-encode the previous frames in the MP4 file and cause image quality loss. If that's not the case, then I'd love to hear your thoughts. – Geuis Aug 18 '17 at 20:33
0

Everything is possible!

Let's image, you have a /directory/ per video animation and files like img0001.png, img0002.png. You have 3 ways:

  1. Wait all images, img0001.png, img0002.png ... img0100.png to be in directory, run ffmpeg, get mp4 and remove images (current way)
  2. Write application in C with ffmpeg libraries: wait every single image, decode it in memory, remove from disk immediately and feed to encoder in libavcodec. When you got last image, for example img0100.png, you feed it to encoder and call something like flush() to complete image, so your mp4 will be completed. Drawback of this method is memory consumption - your process will live until all images processed, so if you downloading it long time, process will consume some memory all this time!
  3. You can try to implement same in bash script using pipes:

Here we got any input, list files for example:

`    ls -1 | grep "jpg$" | while read filename; do`

Then unpack images:

`    ffmpeg -v 0 -nostdin -i "$filename" -f rawvideo -s 120x60 -pix_fmt rgb24 - `

And encode it:

`    done | ffmpeg -nostdin -f rawvideo -s 120x60 -r 10 -pix_fmt rgb24 -i - -s 320x240 -vcodec libx264 -y res.mp4`

I think, you got idea.

0

MP4 is a compressed file structure. Once a compressed file is closed to write, naive attempts to append to it are more likely to corrupt it than append to it.

@Bukkojot got the right idea - extract the file to an uncompressed format, append your images, and recompress the file. His description is really an optimization of the approach that streams the decompression and recompression phases for existing video in parallel thread, but it illustrates the point.

Since MP4 is a lossy compression, every time you decompress the video for re-rendering you lose quality. I would recommend keeping the uncompressed video in a directory and simply re-rendering the video from scratch with every file you append.

  • 2
    MP4 is not a compressed file structure; it's a container, and it's not stored with any sort of compression. It usually contains bitstreams which encode lossy and compressed representations of their source data. But appending occurs at the packet level and codec internals are only relevant so far as to ensure that the consuming player can correctly display both the original and the appended data. ffmpeg can (sort of) trivially generate a new MP4 from multiple inputs without re-encoding anything. The key hurdle here is for the appendage to match existing codec properties just well enough. – Gyan Sep 30 '17 at 5:12
  • 1
    For H.264 in MP4, there are hacks whereby it's possible to append streams which don't need to match i.e. different resolution, profile..etc. Codec ID is set as avc3 but very few players are set to handle such streams. – Gyan Sep 30 '17 at 5:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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