1
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.

Jan Hrcek
  • 626
  • 11
  • 24
McBear Holden
  • 5,741
  • 7
  • 33
  • 55

1 Answers1

2

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
HTNW
  • 27,182
  • 1
  • 32
  • 60
  • Immensely helpful. I actually figure it out already. Could you also give me a hint on how to generate the output file names? I want to change from mp4 to mp3. I can't figure out how to use the sed command to do the substitution. – McBear Holden Oct 10 '17 at 20:43
  • 1
    I wouldn't use `sed`. Just use the `Text` library's functions. `init filename <> "3"` should do it (`init` takes all but last character (all but the last `'4'`), `<> "3"` adds a `"3"` on the end). – HTNW Oct 10 '17 at 21:03
  • Smart!. How about if the `procs` raises an exception? How to manage that exception and throw some messages and continue the process to other files? @HTNW – McBear Holden Oct 10 '17 at 21:07
  • 1
    `procs` throws the `ProcFailed` exception on failure. `proc` will give you the error code and let you deal with it. [See the docs](https://hackage.haskell.org/package/turtle-1.4.4/docs/) for details. – HTNW Oct 10 '17 at 21:26
  • 1
    Is it possible to do parallel processing on those files? @HTNW – McBear Holden Oct 10 '17 at 21:44
  • @osager I'm not sure. Check the docs. You might be able to use `forkIO`, but don't quote me on that. – HTNW Oct 10 '17 at 22:31