4

背景
我编写了一个图像处理应用程序,它使用ffmpeg-light包来获取给定视频文件的所有帧,以便之后程序能够对每个帧应用灰度以及边缘检测算法。

现在我正在尝试将所有帧放回单个视频文件中。

使用
的库 ffmpeg-light-0.12.0
JuicyPixels-3.2.8.3
...

我尝试了什么?
老实说,我并没有真正尝试过任何事情,因为我有点不知道从哪里开始以及如何开始。我看到有一个名为Command允许使用命令行运行进程/命令的包。有了它,我可以使用 ffmpeg (not ffmpeg-light) 从图像文件中创建一个视频,我必须先将其保存到硬盘驱动器中,但这有点笨拙。

ffmpeg-lighton hackage ( ffmpeg-light docu ) 的文档中,我发现 frameWriter 函数听起来很有希望。

frameWriter :: EncodingParams -> FilePath -> IO (Maybe (AVPixelFormat, V2 CInt, Vector CUChar) -> IO ()) 

我猜FilePath这将是存储视频文件的位置,但我真的无法想象如何将帧EncodingParams应用于此功能。


我可以访问的其他人:

  • r, g, b,a以及y. a价值观
  • 图像宽度/高度/格式

问题
有没有办法使用ffmpeg-light包来实现这一点?

由于该ffmpeg-light软件包在从图像转换为视频时缺少文档,我非常感谢您的帮助。(我不希望有一个完全有效的解决方案。)

代码
读取帧的代码:

-- Gets and returns all frames that a given video contains
getAllFrames :: String -> IO [(Double, DynamicImage)]
getAllFrames vidPath = do 
  result <- try (imageReaderTime $ File vidPath) :: IO (Either SomeException (IO (Maybe (Image PixelRGB8, Double)), IO()))
  case result of 
    Left ex -> do 
                 printStatus "Invalid video-path or invalid video-format detected." "Video" 
                 return []
    Right (getFrame, _) -> addNextFrame getFrame [] 

-- Adds up all available frames to a video.
addNextFrame :: IO (Maybe (Image PixelRGB8, Double)) -> [(Double, DynamicImage)] -> IO [(Double, DynamicImage)]
addNextFrame getFrame frames = do
  frame <- getFrame
  case frame of 
    Nothing -> do 
                 printStatus "No more frames found." "Video"
                 return frames
    _       -> do                             
                 newFrameData <- fmap ImageRGB8 . swap . fromJust <$> getFrame 
                 printStatus ("Frame: " ++ (show $ length frames) ++ " added.") "Video"
                 addNextFrame getFrame (frames ++ [newFrameData]) 

我卡在哪里/应该将图像转换为视频的代码:

-- Converts from several images to video
juicyToFFmpeg :: [Image PixelYA8] -> ?
juicyToFFmpeg imgs = undefined
4

1 回答 1

4

免责声明:不熟悉这些库。从类型签名和文档中收集的信息。

使用Codec.FFmpeg.Juicy

Codec.FFmpeg.Juicy.imageWriter ::
  JuicyPixelFormat p =>
  EncodingParams ->
  FilePath ->
  IO (
    Maybe (Image p) -> 
    IO ()
  )

定义

instance JuicyPixelFormat PixelYA8 where
  juicyPixelFormat _  = _ -- in memory format of PixelYA8

juicyToFFmpeg :: [Image PixelYA8] -> FilePath -> IO ()
juicyToFFmpeg is fp = do writer <- imageWriter params fp
                         -- give Just image data to writer to append it
                         forM_ is (writer . Just)
                         writer Nothing -- finalize, or else you'll break it
   where params :: EncodingParams
         params = _ -- Figure out what fps, width, height, etc. you want (hardcode? parameters to juicyToFFmpeg? fold on is?)

旧答案

juicyToFFmpeg :: [Image PixelYA8] -> FilePath -> IO ()
juicyToFFmpeg is fp = do writer <- frameWriter (findEncodingParams is) fp
                         forM_ is $ \img -> let form = imgForm img
                                                dims = imgDims img
                                                pixs = imgData img
                                            in writer $ Just (form, dims, pixs)
                         writer Nothing
   where findEncodingParams = _
         imgForm :: Image PixelYA8 -> AVPixelFormat
         imgForm = _ -- however your images are encoded
         imgDims :: Image PixelYA8 -> V2 Int
         imgDims = _ -- duh
         imgData :: Image PixelYA8 -> Vector CUInt
         imgData = _ -- Encode as a bunch of integers, following the value of imgForm
于 2017-10-23T19:30:29.523 回答