2015-12-18 15 views
5

私はfsmpeg-light、JuicyPixelsとglossを使って、Haskellでビデオを表示しています。私は自動的に再生しているビデオのメタデータを見つけたいと思いますが、まだその方法を見つけていません。haskellでffmpeg-lightを使ってmp4メタデータを見つける方法は?

ビデオの解像度やフレームレートなどのメタデータにアクセスしたいと思います。

私を助けることができますか?

EDIT:

私はあなたのソリューション@CRDrostを試してみましたが、ビデオは現在、2倍、通常の速度で再生されています。私は関数imageReaderTimeが間違ったタイムスタンプを与えていると仮定します。

EDIT 2:

異常な再生速度は、ffmpegの光ライブラリのバグです。私はissueをgithubリポジトリにオープンしました。

私の更新されたコード:

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 

答えて

1

(a)のIはvoid cleanupが冗長とちょうどcleanup作品ですが、私はあなたがそのIO()値が正確に何をするかは100%を確認していないが好きだと思う

FPSを直接読む方法はありませんが、imageReaderTimeでは秒単位のタイムスタンプが生成されます。これは良い指標となります。タイムスタンプを伝播するには、変更する必要があります:

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

は次に、あなたが言う:あなたはFloatではなくDoubleを使用する必要がありますframeAtにパラメータとしてapprox_fpsを渡すことができ

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

または何らかの型強制機能を使用することができる。

しかし、何をやっているため、どのような良いかもしれないことのようなものを持っていることです。

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

これはリストを取り、最初の要素(タイムスタンプ)すべての要素をドロップするには、要求された時間に満ちませんそれ以降に発生する最初のペアの2番目の要素(ピクチャ)を返します。 FPS推測は必要ありません。

関連する問題