Haskell - 使用 ffmpeg-light 包将多个图像文件转换为一个视频文件
Haskell - Turning multiple image-files into one video-file using the ffmpeg-light package
背景
我编写了一个图像处理应用程序,它使用 ffmpeg-light
包来获取给定视频文件的所有帧,以便程序之后能够对每个帧应用灰度和边缘检测算法.
现在我正在尝试将所有帧放回一个视频文件中。
已用库
ffmpeg-light-0.12.0
JuicyPixels-3.2.8.3
...
我尝试了什么?
老实说,我并没有真正尝试过任何东西,因为我有点不知道从哪里开始以及如何开始。我看到有一个名为 Command
的包,它允许 运行 processes/commands 使用命令行。有了它,我可以使用 ffmpeg(不是 ffmpeg-light
)从图像文件中创建一个视频,我必须先将其保存到硬盘驱动器,但这有点 hacky。
在 ffmpeg-light
关于 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
免责声明:不熟悉这些库。从类型签名和文档中收集的信息。
使用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
背景
我编写了一个图像处理应用程序,它使用 ffmpeg-light
包来获取给定视频文件的所有帧,以便程序之后能够对每个帧应用灰度和边缘检测算法.
现在我正在尝试将所有帧放回一个视频文件中。
已用库
ffmpeg-light-0.12.0
JuicyPixels-3.2.8.3
...
我尝试了什么?
老实说,我并没有真正尝试过任何东西,因为我有点不知道从哪里开始以及如何开始。我看到有一个名为 Command
的包,它允许 运行 processes/commands 使用命令行。有了它,我可以使用 ffmpeg(不是 ffmpeg-light
)从图像文件中创建一个视频,我必须先将其保存到硬盘驱动器,但这有点 hacky。
在 ffmpeg-light
关于 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
免责声明:不熟悉这些库。从类型签名和文档中收集的信息。
使用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