-
Notifications
You must be signed in to change notification settings - Fork 28
Description
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:
- Why does
unfoldM readermiss two frames of the video? If I run this function repeatedly,video.mp4gets one frame shorter every time. And if I check the number of frames withffmpegbefore running the function and then printlength oldFrames, it's always 2 frames shorter than whatffmpegreported. - 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.