Search code examples
haskellhaskell-turtle

Haskell Turtle Script: How to consume Shell


import Turtle
import Prelude hiding (FilePath)
import Data.Text hiding (find)
main = do
  f <- view $ format fp  <$> find (suffix ".mp4") "/Users/me/videos"
  procs "ffmpeg" ["-vn","-acodec","libmp3lame","-ac","2","-ab","160k","-ar","48000","-i"] empty

Basically I want to feed all the video filenames to ffmpeg. Two questions:

  1. How to combine the procs with Shell streams?
  2. ffmpeg takes two inputs: one for -i and one for the output filename. What is the best practise to implement this with Turtle?

I've seen the foldIO function that looks promising. But I can't figure out how to use it.


Solution

  • Don't use view like that. You use that to run a Shell, and it prints the resulting values and makes them inaccessible to you. Shell itself is a monad, so you should build up a Shell action, then run with with view or sh (to discard the values without printing). (They're terminal functions; you use them only when you're done doing what you're doing). In fact, MonadIO Shell, so anything you can do in IO you can do in Shell (via liftIO :: MonadIO m => IO a -> m a).

    main = sh $ do -- You don't want to print the output of this Shell (a bunch of ()s)
      filename <- format fp <$> find (suffix ".mp4") "/Users/me/videos"
      let output = findOtherName filename -- Find the output arg for ffmpeg
      procs "ffmpeg" ["-vn","-acodec","libmp3lame","-ac","2","-ab"
                     ,"160k","-ar","48000","-i",filename,output  ] -- Just add them on
    

    This is comparable to

    #!/bin/sh
    for filename in /Users/me/videos/*.mp4; do
        output="`findOtherName "$filename"`"
        ffmpeg -vn -acodec libmp3lame -ac 2 -ab 160k -ar 48000 -i "$filename" "$output"
    done