import Codec.FFmpeg import Codec.Picture import Control.Applicative import Control.Monad.Error import Control.Monad.Trans.Maybe import qualified Data.Vector.Storable as V import System.Environment -- The example used in the README firstFrame :: IO (Maybe DynamicImage) firstFrame = do (getFrame, cleanup) <- frameReaderT "myVideo.mov" (runMaybeT $ getFrame >>= toJuicyT) <* cleanup -- | Generate a video that pulses from light to dark. pulseVid :: IO () pulseVid = do boom <- frameWriter (defaultParams sz sz) "pulse.mov" let go :: Int -> Int -> Int -> IO () go 600 _ _ = boom Nothing go n d i = do boom (Just $ V.replicate (fromIntegral $ sz*sz*3) (fromIntegral i)) let i' = i + d if i' < 100 then go (n+1) 1 101 else if i' > 255 then go (n+1) (-1) 254 else go (n+1) d i' go 0 (-1) 255 where sz = 64 testEncode :: IO () testEncode = initFFmpeg >> pulseVid >> putStrLn "All done!" testDecode :: FilePath -> IO () testDecode vidFile = do initFFmpeg (getFrame, cleanup) <- frameReaderTime vidFile frame1 <- getFrame case frame1 of Just (avf,ts) -> do putStrLn $ "Frame at "++show ts saveJuicy "frame1.png" avf Nothing -> putStrLn "No frame for me :(" replicateM_ 299 getFrame frame2 <- getFrame case frame2 of Just (avf,ts) -> do putStrLn $ "Frame at "++show ts saveJuicy "frame2.png" avf Nothing -> putStrLn "No frame for me :(" cleanup putStrLn "All done!" main :: IO () main = do args <- getArgs case args of [] -> testEncode [vidFile] -> testDecode vidFile _ -> error usage where usage = unlines [ "Usage: demo [videoFile]" , " If no argument is given, a test video named " , " pulse.mov is generated." , "" , " If a file name is given, then two frames are " , " extracted: the first frame, and the 301st." , " These are saved to frame1.png and frame2.png" ]