Haskell - Преобразование нескольких изображений в видеофайл - функция frameWriter ffmpeg-lights не работает
ситуация
В настоящее время я работаю над приложением для обработки изображений, которое использует ffmpeg-light для извлечения всех кадров данного видеофайла, чтобы впоследствии программа могла применять оттенки серого, а также алгоритмы обнаружения краев для каждого из кадров.
С помощью дружественных стековых потоков мне удалось настроить метод, позволяющий конвертировать несколько изображений в один видеофайл с помощью ffmpeg-lights' frameWriter
функция.
проблема
Приложение работает нормально до момента, когда оно попадает в frameWriter
функция, и я не знаю почему, так как нет ошибок или сообщений об исключениях. (ОС: Win 10 64bit)
Что я пробовал?
Я старался..
- разные версии ffmpeg (от 3.2 до 3.4).
- ffmpeg.exe с помощью командной строки, чтобы проверить, отсутствуют ли какие-либо кодеки, но любое преобразование, которое я пробовал, работало.
- разные комбинации EncodingParams: например.. ширина EncodingParams высота fps (Nothing) (Nothing) "средний"
Вопрос
К сожалению, ничего из вышеперечисленного не сработало, и в Интернете не хватает информации для этого конкретного случая. Может быть, я пропустил что-то важное (например, флаги GHC или что-то) или сделал большую ошибку в моем коде. Вот почему я должен спросить вас: есть ли у вас какие-либо предложения / советы для меня?
Пакеты Haskell
- ffmpeg-light-0.12.0
- JuicyPixels-3.2.8.3
Код
{--------------------------------------------------------------------------------------------
Applies "juicyToFFmpeg'" and "getFPS" to a list of images and saves the output-video
to a user defined location.
---------------------------------------------------------------------------------------------}
saveVideo :: String -> [Image PixelYA8] -> Int -> IO ()
saveVideo path imgs fps = do
-- program stops after hitting next line --
frame <- frameWriter ep path
------------------------------------------------
Prelude.mapM_ (frame . Just) ffmpegImgs
frame Nothing
where ep = EncodingParams width height fps (Just avCodecIdMpeg4) (Just avPixFmtGray8a) "medium"
width = toCInt $ imageWidth $ head imgs
height = toCInt $ imageHeight $ head imgs
ffmpegImgs = juicyToFFmpeg' imgs
toCInt x = fromIntegral x :: CInt
{--------------------------------------------------------------------------------------------
Converts a single image from JuicyPixel-format to ffmpeg-light-format.
---------------------------------------------------------------------------------------------}
juicyToFFmpeg :: Image PixelYA8 -> (AVPixelFormat, V2 CInt, Vector CUChar)
juicyToFFmpeg img = (avPixFmtGray8a, V2 (toCInt width) (toCInt height), ffmpegData)
where toCInt x = fromIntegral x :: CInt
toCUChar x = fromIntegral x :: CUChar
width = imageWidth img
height = imageHeight img
ffmpegData = VS.map toCUChar (imageData img)
{--------------------------------------------------------------------------------------------
Converts a list of images from JuicyPixel-format to ffmpeg-light-format.
---------------------------------------------------------------------------------------------}
juicyToFFmpeg' :: [Image PixelYA8] -> [(AVPixelFormat, V2 CInt, Vector CUChar)]
juicyToFFmpeg' imgs = Prelude.foldr (\i acc -> acc++[juicyToFFmpeg i]) [] imgs
{--------------------------------------------------------------------------------------------
Simply calculates the FPS for image-to-video conversion.
-> frame :: (Double, DynamicImage) where Double is a timestamp of when it got extracted
---------------------------------------------------------------------------------------------}
getFPS :: [(Double, DynamicImage)] -> Int
getFPS frames = div (ceiling $ lastTimestamp - firstTimestamp) frameCount :: Int
where firstTimestamp = fst $ head frames
lastTimestamp = fst $ last frames
frameCount = length frames
1 ответ
Я подозреваю, что проблема связана с окружением Windows и использованием ffmpeg из Haskell (т.е. ffmpeg-simple)
Мне удалось успешно скомпилировать и запустить ваш модуль в Ubuntu 16.04, хотя я получил ошибку времени выполнения от ffmpeg:
$ ./main
[NULL @ 0x1ea6900] Unable to find a suitable output format for 'foo.avi'
main: Couldn't allocate output format context
CallStack (from HasCallStack):
error, called at src/Codec/FFmpeg/Encode.hs:214:17 in ffmpeg-light-
0.12.0-DYHyy7pUAhZ7WHcd6Y2mLO:Codec.FFmpeg.Encode
Кажется, что вышеупомянутая ошибка может быть исправлена с помощью настройки некоторых аргументов ffmpeg, но, поскольку это не та проблема, с которой вы сталкиваетесь, я решил не идти дальше с ее отладкой.
На всякий случай мой main
:
main :: IO ()
main = do
Right (ImageYA8 img) <- readPng "foo_ya.png"
saveVideo "foo.avi" (replicate 10 img) 10
Я запустил то же самое на Windows 7 64-битной и, похоже, я не смог полностью удовлетворить зависимости.
Компиляция и установка зависимостей в Windows:
> stack exec -- pacman -Syu
> stack exec -- pacman -S mingw-w64-x86_64-gtk3
> stack exec -- pacman -S mingw-w64-x86_64-pkg-config
> stack exec -- pacman -S mingw-w64-x86_64-ffmpeg
> stack --install-ghc --resolver lts-9.10 exec --package vector --package JuicyPixels --package ffmpeg-light -- ghc main.hs -O2 -threaded
> stack exec -- main.exe
Приводит к ошибке всплывающего окна при запуске в cmd
(ps
просто выходит)
Не удалось найти точку входа в процедуру inflateValidate в библиотеке динамических ссылок zlib1.dll
Я не специалист по разработке под Windows, поэтому чувствую, что что-то упустил. Надеюсь, моя попытка будет хоть немного полезной.