Play CLI defines helpers to deal with UNIX command with Play Framework iteratees.
cat list.txt | wc | mail -s "Count" gre@greweb.fr
val chunkedWaveStream =
rawStream &> chunker &> waveEncoder
&>
very similar to |
val chunkedAudioStream =
rawStream &> CLI.pipe("sox -t raw - -t ogg -")
Play CLI relies on Process to create commands.
Play CLI is implemented using Iteratee paradigm.
CLI.enumerate
CLI.pipe
CLI.consume
def enumerate (cmd: ProcessBuilder)
: Enumerator[Array[Byte]]
def pipe (command: ProcessBuilder)
: Enumeratee[Array[Byte], Array[Byte]]
def consume (command: ProcessBuilder)
: Iteratee[Array[Byte], Int]
val find = CLI.enumerate("find .")
Ok.stream(find)
Simple.
val tail = CLI.enumerate("tail -f /var/log/nginx/access.log")
val (sharedTail, _) = Concurrent.broadcast(tail)
def stream = Action(Ok.stream(sharedTail))
val convert14colors = CLI.pipe("convert - -colors 14 png:-")
Ok.stream(
Enumerator.fromFile("nyancat.jpg") &>
convert14colors)
Image stream processing: Easy!
val src = "http://radio.hbr1.com:19800/ambient.ogg"
val addEchoToOgg =
CLI.pipe("sox -t ogg - -t ogg - echo 0.5 0.7 60 1")
def webRadioWithEcho = Action {
Ok.stream(proxy(src)(addEchoToOgg &> _))
.withHeaders(CONTENT_TYPE -> "audio/ogg")
}
This works! But let's do better...
val stream: Enumerator[Array[Byte]] = getStream("http://.../Sintel.2010.1080p.mkv")
val scaleVideoHalf = CLI.pipe("ffmpeg -i pipe:0 -vf scale=iw/2:-1 -f avi pipe:1")
val scaledVideo = stream &> scaleVideoHalf
Ok.stream(scaledVideo)
.withHeaders(CONTENT_TYPE -> "video/avi")
val find = CLI.enumerate("find .")
// Re-usable - one Process each time
val consume = CLI.consume("sideEffect")
// apply this iteratee once
CLI.pipe("command")
is stopped if:
Iteratee[Array[Byte], Int]
Enumerator[Either[Array[Byte], Int]]
Enumeratee[Array[Byte], Either[Array[Byte], Int]]
Concurrent.broadcast
"fr.greweb" %% "playcli" % "0.1"