0

I have a .wmv file which I want to convert to .wav file and I am using ffmpeg for the same, the command is as follows:

ffmpeg -i file.wmv -ar 8000 -sample_fmt s16 -f wav pipe:1

the pipe:1 outputs the output wave file in STDOUT. I want to capture that wave file from STDOUT and pass it as a command line argument to my executable called foo. I want to do the conversion from wmv to wav on the fly rather than saving the .wav file. Things I have tried are as follows but none of them seem to work:

./foo $(ffmpeg -i file.wmv -ar 8000 -sample_fmt s16 -f wav pipe:1)

./foo $(<(ffmpeg -i file.wmv -ar 8000 -sample_fmt s16 -f wav pipe:1))

ffmpeg -i file.wmv -ar 8000 -sample_fmt s16 -f wav pipe:1 | xargs ./foo

ffmpeg -i file.wmv -ar 8000 -sample_fmt s16 -f wav - | ./foo -
5
  • Why not just pipe it and have your program read from stdin? Commented Feb 22, 2017 at 21:36
  • 1
    The design of the executable is not in my control Commented Feb 22, 2017 at 21:39
  • What about using bash process redirection? Your second example, but with just <(ffmpeg ...), and not the $( and ) ? The result of that would look something like ./foo /dev/fd/63, where the fd was populated by the output of the command. Commented Feb 22, 2017 at 21:59
  • Oh, I was too slow, chepner already got it. Commented Feb 22, 2017 at 22:01
  • ffmpeg -i file.wmv -ar 8000 -sample_fmt s16 -f wav - | ./foo /dev/stdin is another option, subject to most of the caveats relevant to process substitution (FIFO, non-seekable, &c) Commented Feb 22, 2017 at 22:06

1 Answer 1

2

I think your second attempt is close:

./foo <(ffmpeg ...)

The process substitution expands to a name, which foo can open like any other file. The contents of this "file" are the output from ffmpeg.

Note, however, this will not work if foo expects a seekable file; the output of ffmpeg is still a stream which is not buffered in memory. If foo expects to be able to move back and forth through the file, you need to use an actual file. (ffmpeg ... > tmp; ./foo tmp)


In the first case, you are trying to pass the contents of the output stream as an argument, similar to ./foo "$(cat some.mp4)".

In the third case, you are treating the output of ffmpeg as the name of a file.

The fourth case would work if foo were written to understand - as a stand-in name for standard input. That is a program convention, not something provided by the shell.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. but I am little confused as to how the <(ffmpeg ...) syntax serves as a command line argument as opposed to stdin.
Process substitution is, in some sense, a way of creating a temporary file. Try echo <(:) (: being the do-nothing command). The output is the name of the "file" that the process substitution creates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.