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.

1

1 Answer 1

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.

10
  • does this not send both containers to both (myprogram...) instances?
    – mikeserv
    Commented Oct 18, 2014 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
    Commented Oct 18, 2014 at 17:16
  • 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
    Commented Oct 18, 2014 at 17:40
  • 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
    Commented Oct 18, 2014 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
    Commented Oct 18, 2014 at 18:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .