Skip to content

Is it possible to append a frame to an existing video? #57

@burkaman

Description

@burkaman

I'd like to append a new frame to the end of an existing video file. I'm not sure if this is possible (but I haven't figured out how), not yet possible (but worth me working on a PR to support it), or impossible (not really how ffmpeg works, or would require a major rewrite of this package or something).

I first tried simply opening an existing video with imageWriter and writing a single frame, which overwrites the whole video with just the new frame. I'm assuming this is the expected behavior.

Next, I tried reading all the frames of the existing video with imageReader, and then writing them all back out, plus the new frame, with imageWriter. This almost works, but with two significant problems. First, it's obviously very slow, but also, my method of grabbing all the frames seems to drop 2 of them? Given a 125 frame video, it reads 123 frames, and then adds my new frame, so every time I run the function my video actually ends up one frame shorter. I haven't yet determined which frames I'm failing to read.

Here's my code (somewhat simplified so I'm not 100% sure it compiles, but hopefully it gets the point across):

addFrame :: Image a -> IO ()
addFrame image = do
  initFFmpeg  
  (reader, cleanup) <- imageReader (File "/path/to/video.mp4") :: IO (IO (Maybe (Image PixelRGB8)), IO ())
  oldFrames <- unfoldM reader
  cleanup
  let newFrames = oldFrames ++ [image]
  writer <- imageWriter (defaultParams width height) "/path/to/video.mp4" :: IO (Maybe (Image PixelRGB8) -> IO ())
  mapM writer (map Just newFrames)
  writer Nothing
  return ()

So I have two questions:

  1. Why does unfoldM reader miss two frames of the video? If I run this function repeatedly, video.mp4 gets one frame shorter every time. And if I check the number of frames with ffmpeg before running the function and then print length oldFrames, it's always 2 frames shorter than what ffmpeg reported.
  2. Is there a way to avoid this and directly append the new frame? If it's possible in theory I'd be willing to work on a PR, but if it's out of the scope of this package then I'll find another way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions