How to combine two ffmpeg bin script into one script - linux

#!/bin/bash
cmd="ffmpeg -re -i http://10.10.10.3:9981/stream/channelnumber/9 -vcodec copy -acodec copy -f mpegts udp://224.2.2.119:2001?pkt_size=188&localaddr=192.168.2.119"
until $cmd > /dev/null 2>&1 < /dev/null; do
echo "restarting ffmpeg command..."
sleep 2
cmd="ffmpeg -re -i http://10.10.10.3:9981/stream/channelnumber/15 -vcodec copy -acodec copy -f mpegts udp://224.2.2.120:2002?pkt_size=188&localaddr=192.168.2.119"
until $cmd > /dev/null 2>&1 < /dev/null; do
echo "restarting ffmpeg command..."
sleep 2
done

Combined command:
ffmpeg -i http://10.10.10.3:9981/stream/channelnumber/9 -i http://10.10.10.3:9981/stream/channelnumber/15 -map 0 -c copy -f mpegts "udp://224.2.2.119:2001?pkt_size=188&localaddr=192.168.2.119" -map 1 -c copy -f mpegts "udp://224.2.2.120:2002?pkt_size=188&localaddr=192.168.2.119"
Do not use -re for live input streams.

Related

First character disappears when piping script with ffmpeg to bash

I often create bash scripts with bash and pipe the results to bash... When I do this:
echo -e "ffmpeg -loglevel quiet -f lavfi -i nullsrc -t 1 -f null /dev/null\necho foo"|bash
I get
bash: line 2: cho: command not found
Where did the 'e' of 'echo' go? What does ffmpeg do there? Other commands work fine.
Note also:
echo -e "ffmpeg -loglevel quiet -f lavfi -i nullsrc -t 1 -f null /dev/null\necho foo" > /tmp/foo.sh
bash /tmp/foo.sh #works
bash < /tmp/foo.sh #doesn't
ffmpeg also reads from standard input, which it inherits from its parent process, which is the bash process reading your command line. This means ffmpeg is reading the e from echo following the new line.
One fix is to redirection standard input for ffmpeg:
echo -e "ffmpeg -loglevel quiet -f lavfi -i nullsrc -t 1 -f null /dev/null < /dev/null \necho foo"|bash
However, I can't help but point out that there isn't really any reason to run a script like this. If you want it in a separate process, start a subshell:
(
ffmpeg -loglevel quiet -f lavfi -i nullsrc -t 1 -f null /dev/null
echo foo
)

Q: Bash script infinite loop causing ffmpeg spam

Can't seem to figure this one out... I have a set up NGINX server with the excellent RTMP extension and everything is working fine. However, I'm trying to restream/push a copy of a couple specific streams that need to be streamed in another RTMP stream application (specifically, these streams are streamed to application "static" but in the current situation also need to be pushed over to "live"). The process of restreaming/pushing a stream in NGINX-RTMP is relatively simple, however, in my case I need to selectively push a couple of streams instead of every stream being streamed to the application "static".
Idea is to have NGINX-RTMP pass the stream name off to the bash script, which then does the restreaming without interrupting any other streams or services.
With some success, I've tried doing this by creating a bash scrip..
The relevant NGINX config bit that runs the bash script is:
exec_publish /etc/nginx/rtmp_conf.d/stream_id.sh $name;
I tried it with an "if / else"
if [ $1 == "stream_name_1" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_1 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_0
elif [ $1 == "stream_name_2" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_2 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_1
elif [ $1 == "stream_name_3" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_3 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_2
elif [ $1 == "stream_name_4" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_4 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_3
else
echo "FAIL" >> /etc/nginx/rtmp_conf.d/stream.log && echo date > /etc/nginx/rtmp_conf.d/stream.log
exit
fi
And I tried it with Switches
case "$1" in
"stream_name_1")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_1 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_0
;;
"stream_name_2")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_2 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_1
;;
"stream_name_3")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_3 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_2
;;
"stream_name_4")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_4 -vcodec libx264 -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_3
;;
echo "FAIL " >> /etc/nginx/rtmp_conf.d/stream.log && echo date > /etc/nginx/rtmp_conf.d/stream.log
esac
Problem with both is that they both end up spamming a ton of ffmpeg processes ... and I don't know why - I've tried changing the code but I either end up with ffmpeg not firing at all or spamming the server.
Need more info.
What do ffmpegs say?
Have you checked the $1?
I would like to see the entire script.
It turns out that in my situation ffmpeg didn't like the argument flag "-vcodec x264" (weird because the source stream is encoded with x264, but oh well), changing it to use "copy" audio and video codec fixed my problem - ffmpeg doesn't spawn tens of processes, each trying to use abnormal resource amounts, anymore.
The examples for the working code in my case is:
To initiate the bash scripts I'm placing this in my NGINX config (which passes the incoming stream name to the bash script as by design of the RTMP module):
exec_publish /etc/nginx/rtmp_conf.d/stream_id.sh $name;
Using switches:
#!/bin/bash
case "$1" in
"stream_name_1")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_1 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_0
;;
"stream_name_2")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_2 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_1
;;
"stream_name_3")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_3 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_2
;;
"stream_name_4")
ffmpeg -re -i rtmp://127.0.0.1:2000/static/stream_name_4 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_3
;;
esac
And using If/Else:
#!/bin/bash
if [ $1 == "stream_name_1" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/$1 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_0
elif [ $1 == "stream_name_2" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/$1 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_1
elif [ $1 == "stream_name_3" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/$1 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_2
else [ $1 == "stream_name_4" ]; then
ffmpeg -re -i rtmp://127.0.0.1:2000/static/$1 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:2000/live/live_3
fi

ffmpeg: How to concat audio files and add background music in a single command?

Need to concat audio files and add background music in a single command.
Right now I use the following commands to do so,
To concat:
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 -i 5.mp4 -i 6.mp4 -i 7.mp4 -i 8.mp4 -i 9.mp4 -i 10.mp4 -filter_complex '[0:0][1:0]concat=n=10:v=0:a=1[out]' -map '[out]' -strict -2 -y 10_final.mp4
To add background music:
ffmpeg -i 10_final.mp4 -i music.mp4 -filter_complex "[0:a]volume=1dB[a0];[1:a]volume=0.5[a1];[a0][a1]amerge=inputs=2[a]" -map "[a]" -ac 1 -ab 32000 -ar 22050 -strict -2 -y 10_with_music.mp4
But his process is a quite time-consuming process as every time the file read/write happening to the output.
Is there a way I can merge these two above commands to a single so that the command should be optimized.
Use
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 -i 5.mp4
-i 6.mp4 -i 7.mp4 -i 8.mp4 -i 9.mp4 -i 10.mp4
-i music.mp4
-filter_complex '[0:0][1:0]...[9:0]concat=n=10:v=0:a=1,volume=1dB[a0];
[10]volume=0.5dB[a1];[a0][a1]amerge[a]'
-map '[a]' -strict -2 -y 10_with_music.mp4

ffmpeg to convert .avi, .mp4, .mp3, .flv, .mkv to mp4

I searching for a script that contains all of that attributes like the title.
I have done one simple but that is only for one attribute so far and i do not want one script for each of all attributes to not be confused.
Like this, running the script for like 10 minutes to see if there is any file that consist .flv and the automatic doing a convert for the file to a mp4 attribute.
#!/bin/bash
# Convert all flv to mp4
ext=.mp4
for file in *.flv; do
currmov=$file$ext
ffmpeg -r 15 -i $file -b 296k -s 640x320 -vcodec mpeg4 -acodec aac $currmov
done
Thanks for help!
/M
For all extensions:
for file in *.{flv,avi,mp3,mkv}; do
target="${file%.*}.mp4"
[[ -f "$target" ]] && { echo "skipping $file - $target exists" ; continue; }
echo ffmpeg -r 15 -i "$file" -b 296k -s 640x320 -vcodec mpeg4 -acodec aac "$target"
done
remove the echo before ffmpeg if satisfied
You just need a second loop
for ext in avi mp3 flv mk4; do
for file in *.$ext; do
...
done
done

How to keep stderr output and also redirect it to file

I tried
ffmpeg -i rtsp://172.19.1.34/live.sdp -acodec copy -vcodec copy b.mp4 2>>log.txt 2>&1
to keep stderr output and also redirect it to file.
But it failed.
However, I can keep the stderr output by
ffmpeg -i rtsp://172.19.1.34/live.sdp -acodec copy -vcodec copy b.mp4 2>log.txt
You can redirect stderr to stdout with 2>&1, and then use tee command.
cmd 2>&1 | tee -a log
try this
ffmpeg -i rtsp://172.19.1.34/live.sdp -acodec copy -vcodec copy b.mp4 &> log.txt
or this
nohup ffmpeg -i rtsp://172.19.1.34/live.sdp -acodec copy -vcodec copy b.mp4
and look for nohup.out after the command returns.

Resources