4

I'm using FFmpeg and I have made a custom application which is a TCP server. I 'm using duplicate output in ffmpeg.

What I want is, for each output I want to start my program to listen on a specific port. For example what I can do now:

ffmpeg -i "stream_link" -codec copy -f mpegts - \
    | myprogram -h 127.0.0.1 -p 12345 -f -

My program takes the data from ffmpeg and stores them inside the server. Now, I CAN'T DO the following

ffmpeg -i "stream_link" -codec copy -f mpegts - -codec copy -f flv - \
    | myprogram -h 127.0.0.1 -p 12345 -f - \
    | myprogram -h 127.0.0.1 -p 12345 -f -

I think you got me. I'm trying to output 2 different containers mpegts, flv and open again 2 instances of my program. So how I am able to do it?

This question is only pipe related. I just gave a real example using FFmpeg.

slm
  • 369,824
  • Probable duplicate, see http://unix.stackexchange.com/questions/40277/is-there-a-way-to-pipe-the-output-of-one-program-into-two-other-programs . Andreas Florath's ptee/pipexec answer particularly. – mr.spuratic Oct 18 '14 at 18:43

1 Answers1

6
ffmpeg -i "stream_link" -codec copy -f mpegts - -codec copy -f flv - |  
myprogram -h 127.0.0.1 -p 12345 -f - | 
myprogram -h 127.0.0.1 -p 12345 -f -

So If I understand correctly, you are tryithisng to combine these 2 commands into one.

mpegts format

ffmpeg -i "stream_link" -codec copy -f mpegts - |  
myprogram -h 127.0.0.1 -p 12345 -f - 

flv format

ffmpeg -i "stream_link"  -codec copy -f flv - |  
myprogram -h 127.0.0.1 -p 12345 -f -

So, if my above understanding is correct, I believe you can accomplish it using tee command. You could get more details from this question here.

So, you could rephrase your command as,

 ffmpeg -i "stream_link" -codec copy -f mpegts - -codec copy -f flv - |  
 tee >(myprogram -h 127.0.0.1 -p 12345 -f -) 
     >(myprogram -h 127.0.0.1 -p 12346 -f -) 

However, as user mikeserv points out in his comments,

ffmpeg is writing two streams to one file. Both the mpegts and the flv go to stdout which is the | pipe.

So, the solution would have to involve ffmpeg writing to two distinct files. something like, ffmpeg flv processing -o flvfile, mpegts processing -o mpegtsfile and the two processes reading from the two outputs.

Either that or the process receiving the input would have to parse ffmpeg's output to know at which offset to begin reading their intended streams.

So the problem with the tee approach is that tee could duplicate the ffmpeg's input and two ffmpeg could be used.

So a better solution to this problem would be to use the approach as,

{ { ffmpeg -i "stream_link"            #one input stream
        -codec copy -f flv /dev/fd/3   #duped and processed, out >&3
        -codec copy -f mpegts - |      #duped and processed, out >&1
        myprogram1 >&4                 #receives >&1 on <&0, out >&4
        } 3>&1 | myprogram2            #receives >&3 on <&0, out >&1
} 4>&1                                 #ensures both myprograms write to >&1

When we use the above approach ffmpeg explicitly splits its output. It does depend on being run on a system that understands the /dev/fd/[num] links.

Ramesh
  • 39,297
  • does this not send both containers to both (myprogram...) instances? – mikeserv Oct 18 '14 at 17:13
  • @mikeserv, yeah. But isn't what the question is about? I believe the OP wanted to send the ffmpeg output to 2 processes. Or am I misinformed? – Ramesh Oct 18 '14 at 17:16
  • yeah. So probably I will wait on OP. But his original question was related to pipes and I thought from his example, he meant to send the first command output to 2 other processes. – Ramesh Oct 18 '14 at 17:19
  • Hello, yes i want to combined everything in one command. Also one output of ffmpeg must go to one instance of my program etc. So for mpegts -> my_program in port 12345 and flv -> my_program in port 12346 – user3393046 Oct 18 '14 at 17:32
  • @mikeserv, oh why is it not possible with tee? – Ramesh Oct 18 '14 at 17:36
  • @mikeserv, this example explains tee and so with the OP's description of the problem, I figured it could best fit his need. – Ramesh Oct 18 '14 at 17:38
  • 1
    the wording there isn't exactly correct - tee doesn't split anything - it doubles it. So you can do echo "one output" | tee >(whole output here) >(whole output here) >whole_output_here – mikeserv Oct 18 '14 at 17:40
  • Oh ok. I think I get it. But still it is what the OP wants right? – Ramesh Oct 18 '14 at 17:42
  • 1
    Thanks @mikeserv. I have incorporated your comments. Let me know if it is fine and feel free to edit if you feel I have missed something. – Ramesh Oct 18 '14 at 18:29
  • 2
    I did a little edit - at first only because \nl|pipe doesn't work - you need |pipe\nl, but then I figured some comments might help. Good answer - we were thinking the same thing both times. – mikeserv Oct 18 '14 at 18:53