[erlang-questions] open_port vs. unix pipes

Rapsey <>
Sun Oct 26 16:32:19 CET 2008


Awesome! Thank you.

The stupid bug in my code was:
Port ! {Port, {command, Data}}
instead of:
Port ! {self(), {command, Data}}

It works perfectly.



Sergej


On Sun, Oct 26, 2008 at 3:48 PM, Edwin Fine <> wrote:

> Sergey,
>
> I tried to write an email about this, but found it easier just to write a
> program. It's only 70 lines, so here it is. It's maybe not the best code,
> but I did crank it out as fast as I could, and it does seem to work. I
> haven't actually tested the binary output to see if it's complete and
> correct, but if you specify a file name it does write to the file with no
> complaints.
>
> I hope it helps.
>
> Example usage:
>
> {ok,Bin} = file:read_file("/backups/mp3/Allan Holdsworth/Allan Holdsworth -
> Devil take the hindmost.mp3"),
> Opts =
> [{fmt_in,"mp3"},{fmt_out,"flv"},{file_out,"-"},{stderr_redirect,{file,"/tmp/dtth.out"}],
> {ok, Results} = ffmpeg:convert(Bin,Opts).
> -----------------------
> -module(ffmpeg).
> -author("Edwin Fine").
> -export([convert/2, print_responses/1]).
>
> %% Params are in proplists format:
> %% [Opt] - All opts are mandatory except for overwrite, which defaults to
> false
> %% Opt = {fmt_in, string()}
> %%       {fmt_out, string()} - must be provided
> %%       {file_out, string()} - may be "-", in which case the list of
> binaries returned will contain the data
> %%       {overwrite, true|false} - default true
> %%       {stderr_redirect, {file, string()} | stdin | bit_bucket} - Either
> redirects stderr to a given file, to stdin, or /dev/nul
> %%       {extra, string()} - free format parameters
> %%
> %% If file_out is set to "-", stderr_redirect should really be to file or
> bit_bucket or the returned data will be corrupt
> %%
> %% Example:
> %%
> %% Opts = [{fmt_in, "mp3"}, {fmt_out, "flv"}, {file_out, "/tmp/test.flv"}]
> %%
> %% -> [binary()]
> %%
> %% Returns a list of binaries output by ffmpeg.
> %%
> convert(InputBinary, Opts) when is_binary(InputBinary), is_list(Opts) ->
>     Prog = "/usr/local/bin/ffmpeg",
>     FmtIn = proplists:get_value(fmt_in, Opts),
>     FmtOut = proplists:get_value(fmt_out, Opts),
>     FileOut = proplists:get_value(file_out, Opts),
>     Extra = proplists:get_value(extra, Opts, ""),
>     OverWrite = overwrite(proplists:get_value(overwrite, Opts, false)),
>     Redirect = format_redirect(proplists:get_value(stderr_redirect, Opts,
> {file, "/tmp/ffmpeg.out"})),
>
>     PortCmd = build_port_cmd(Prog, FmtIn, FmtOut, OverWrite, FileOut,
> Redirect, Extra),
>
>     Port = open_port({spawn, PortCmd}, [binary, use_stdio, stream]),
>     port_command(Port, InputBinary),
>     Responses = response_reader(Port),
>     port_close(Port),
>     Responses.
>
> print_responses(Msgs) ->
>     io:format("~s~n", [binary_to_list(list_to_binary(Msgs))]).
>
> response_reader(Port) ->
>     response_reader_loop(Port, []).
>
> response_reader_loop(Port, L) ->
>     receive
>         {Port, {data, Bin}} ->
>             response_reader_loop(Port, [Bin|L]);
>         Other ->
>             io:format("Unexpected: ~p~n", [Other]),
>             response_reader_loop(Port, L)
>     after
>         1000 ->
>             {ok, lists:reverse(L)}
>     end.
>
> build_port_cmd(Prog, FmtIn, FmtOut, OverWrite, FileOut, Redirect, Extra) ->
>     lists:concat([
>             Prog, " -f ", FmtIn, " -i - ", OverWrite, " -f ",
>             FmtOut, " ", FileOut, " ", Extra, Redirect]
>     ).
>
> overwrite(true)  -> "-y";
> overwrite(false) -> "".
>
> format_redirect({file, File}) -> " 2>" ++ File;
> format_redirect(stdin)        -> " 2>&1";
> format_redirect(bit_bucket)   -> " 2>/dev/null".
> ---------------
>
> 2008/10/25 Rapsey <>
>
>> What is the difference for the program that communicates using stdin and
>> stdout, if it is opened using open_port from within erlang or with unix
>> pipes?
>> I'm trying to use open_port with ffmpeg, this works just fine for
>> instance:
>>
>> cat blabla.mp3 | /opt/local/bin/ffmpeg -f mp3 -i - -acodec libfaac -f flv
>> -  > dan.flv
>>
>> But if I use open_port:
>> {ok, Bin} = file:read_file("blabla.mp3"),
>> Port = open_port({spawn, "/opt/local/bin/ffmpeg -f mp3 -i - -acodec
>> libfaac -f flv -"}, [binary, use_stdio, stream]),
>> <<Data:128000/binary, Remain/binary>> = Bin,
>> Port ! {Port {command, Data}}
>>
>> ffmpeg call will fail with:
>> pipe:: Error while opening file
>>
>>
>>
>> /Sergej
>>
>> _______________________________________________
>> erlang-questions mailing list
>> 
>> http://www.erlang.org/mailman/listinfo/erlang-questions
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20081026/8a6a9fb4/attachment.html>


More information about the erlang-questions mailing list