2015-12-18 17 views
5

, JuicyPixels ve parlaklık Haskell ile bir video görüntülemek için. Otomatik olarak oynattığım videoların meta verilerini bulmak istiyorum, ancak henüz bunu yapmanın bir yolunu bulamadım.nasıl Haskell ffmpeg-ışıkla mp4 meta bulmak için? Ben ffmpeg-ışık kullanıyorum

Ben çözünürlük ve videonun kare hızına gibi meta veriler erişmek istiyorum.

Bana yardım edebilir?

DÜZENLEME:

Ben senin çözüm @CRDrost denedi, ancak video şimdi 2x normal hızda oynuyor. ImageReaderTime işlevi yanlış zaman damgalarını veriyor.

DÜZENLEME 2:

anormal oynama hızı ffmpeg ışık kütüphanesinde bir hata. Github deposunda bir issue açtım.

Benim güncellenen kod:

import Graphics.Gloss 
import Codec.FFmpeg 
import Codec.FFmpeg.Juicy 
import Codec.Picture 
import Control.Applicative 
import Data.Maybe 
import Graphics.Gloss.Juicy 
import Control.Monad 
-- import System.IO.Unsafe (unsafePerformIO)-- for debugging purposes 

resolution :: (Int,Int) 
resolution = (640, 360) 

frameCount :: Int 
frameCount = 100 

main :: IO() 
main = do 
    initFFmpeg 
    (getFrame, cleanup) <- imageReaderTime "big_buck_bunny.mp4" 
    frames <- replicateM frameCount $ nextFrame getFrame 
    cleanup 
    animate (InWindow "Nice Window" resolution (10,10)) white (frameAt frames) 

nextFrame :: IO (Maybe (Image PixelRGB8, Double)) -> IO (Picture, Float) 
nextFrame getFrame = mapSnd realToFrac . mapFst fromImageRGB8 . fromJust <$> getFrame 

frameAt :: [(Picture, Float)] -> Float -> Picture 
frameAt list time = fst . head . dropWhile ((< time) . snd) $ list 

mapFst :: (a -> c) -> (a, b) -> (c, b) 
mapFst f (a, b) = (f a, b) -- applies f to first element of a 2-tuple 

mapSnd :: (b -> c) -> (a, b) -> (a, c) 
mapSnd f (a, b) = (a, f b) -- applies f to the second element of a 2-tuple 

cevap

1

(a)void cleanup gereksiz ve sadece cleanup eserler düşünmek ama o IO() değeri tam ne yaptığını değil% 100 eminim gibi.

Ben FPS okumak için doğrudan yol göremiyorum, ama imageReaderTime size iyi bir gösterge verecek saniyede damgaları, üretir. damgası yaymak değiştirmek gerekir:

nextFrame :: IO (Maybe (Image PixelRGB8, Double)) -> IO (Double, Picture) 
nextFrame getFrame = fmap fromImageRGB8 . swap . fromJust <$> getFrame 

Sonra derdi: Eğer Float yerine Double kullanmak zorunda olacak frameAt için parametre olarak approx_fps geçebilir

Nihayet
stampedFrames <- replicateM frameCount $ nextFrame getFrame 
let (tstamps, frames) = unzip stampedFrames 
let approx_fps = fromIntegral (length tstamps)/(maximum tstamps - minimum tstamps) 

ya da bazı tip-zorlama işlevi. Bu listeyi alır

frameAt :: [(Double, Picture)] -> Double -> Picture 
frameAt list time = snd . head . dropWhile ((< time) . fst) $ list 

ilk elemanı (zaman damgası) istenen süreden daha az olduğu tüm unsurları düşer:

Ancak, ne yaptığınızı için, daha iyi ne olabilir gibi bir şey sahip olmaktır ve sonra bundan sonra oluşan ilk çiftin ikinci öğesini (resim) döndürür. FPS tahmin edilmesine gerek yoktur.

İlgili konular