I have 2 blocking shell scripts which I want to have interact with each other. The scripts in question are peerflix (nodejs script) and ffmpeg (a simple bash script).
What happens: Peerflix fires up, feeds data to ffmpeg bash scrip which terminates peerflix on completion.
So once peerflix starts it outputs 2 lines and blocks immediately:
[08:15 PM]-[vagrant#packer-virtualbox-iso]-[/var/www/test]-[git master]
$ node /var/www/test/node/node_modules/peerflix/app.js /var/www/test/flexget/torrents/test.torrent -r -q
listening: http://10.0.2.15:38339/
process: 9601
I have to feed the listening address to the ffmpeg bash script:
#!/bin/sh
ffmpeg -ss 00:05:00 -i {THE_LISTENING_PORT} -frames:v 1 out1.jpg
ffmpeg -ss 00:10:00 -i {THE_LISTENING_PORT} -frames:v 1 out2.jpg
After the bash script is done I have to kill the peerflix script (hence me outputting the PID).
My question is how do I achieve this?
I think you want something like this:
# Start the node process in the background
node /var/www/test/node/node_modules/peerflix/app.js /var/www/test/flexget/torrents/test.torrent -r -q &
# Get the PID of the node process
PID=$!
# Run your stuff
ffmpeg -ss 00:05:00 -i {THE_LISTENING_PORT} -frames:v 1 out1.jpg
ffmpeg -ss 00:10:00 -i {THE_LISTENING_PORT} -frames:v 1 out2.jpg
# Stop the node process
kill $PID
You could put this in one script or have a node script that starts/kills the node process be a wrapper and run another script in the middle. Hope this helps.
Related
I was trying to understand this shell script which uses ffmpeg to take an rtmp input stream and send it to a node.js script. But I am having trouble understanding the syntax. What is going on here?
The script:
while :
do
echo "Loop start"
feed_time=$(ffprobe -v error -show_entries format=start_time -of default=noprint_wrappers=1:nokey=1 $RTMP_INPUT)
printf "feed_time value: ${feed_time}"
if [ ! -z "${feed_time}" ]
then
ffmpeg -i $RTMP_INPUT -tune zerolatency -muxdelay 0 -af "afftdn=nf=-20, highpass=f=200, lowpass=f=3000" -vn -sn -dn -f wav -ar 16000 -ac 1 - 2>/dev/null | node src/transcribe.js $feed_time
else
echo "FFprobe returned null as a feed time."
fi
echo "Loop finish"
sleep 3
done
What is feed_time here? What does it represent?
What is this portion doing - 2>/dev/null | node src/transcribe.js $feed_time?
What is the use of sleep 3? Does this mean that we are sending audio stream to node.js in chuncks of 3 seconds?
feed_time variable represents standard output of ffprobe command. This value needs to be passed to node script.
- character doesn't have special meaning in bash, i.e. it is interpreted by ffmpeg command itself (see here). According to ffmpeg docs:
A - character before the stream identifier creates a "negative"
mapping. It disables matching streams from already created mappings.
2>/dev/null is a redirection that sends standard error output of ffmpeg command to /dev/null device, thus effectively discarding the error output (see here). It is done because you want only the standard output (not error output) to be passed to node script.
| is a pipe. It sends standard output of ffmpeg command to standard input of node script.
sleep just delays execution of a script.
This question already has answers here:
ffmpeg hangs when run in background
(3 answers)
Closed 1 year ago.
I am trying to get ffmpeg to run as a background task in linux, I have been trying to do it like this
ffmpeg -i input.mkv -loglevel panic output.mp4 &
But whenever I run the program it halts in the beginning until I put it as a foreground task fg $1 and then I can leave the task and it runs in the background just fine, how can I make it run from the beginning as a background task without having to put it as a foreground task temporarily?
I have also tried this and it didn't work
ffmpeg -i input.mkv -loglevel panic output.mp4 2> /dev/null &
I just needed to supply some sort of input to ffmpeg so it would run, I just piped nothing into ffmpeg and it runs as a background task, done like so
echo "" | ffmpeg -i input.mkv -loglevel panic output.mp4 2> /dev/null &
Edit:
This same effect can be done by adding -nostdin as a flag to ffmpeg, as demonstrated below
ffmpeg -i input.mkv -nostdin -loglevel panic output.mp4 2> /dev/null &
I have a bash script that is called by a phone system that gets some audio from a URL and (using ffmpeg, mplayer etc.) then pipes it back to the application. The file can have several URL's that are called so if the first one say goes off line or gives a 404 it will go to the next line.
I have an issue where some times the server will produce content however there is no audio. In such a case I want to kill the current PID of ffmpeg, mplayer etc. so that the script should move on.
I can't foreground it and get the last PID since once it's ran in the foreground the media is no longer being piped to the application calling it. I can't use exec in the beginning since if I then issue a kill to the PID the script dies which I don't want.
The script looks something like this:
#!/bin/bash
/usr/bin/ffmpeg -i 'http://1.1.1.1/soft_music' -vn -ar 8000 -ac 1 -f s16le -
/usr/bin/ffmpeg -i 'http://2.2.2.2/soft_music' -vn -ar 8000 -ac 1 -f s16le -
I assume I need to add something that will allow me to log the pid of the current ffmpeg command running so my external script can get it and kill it. Once that's done it will go to the next line and try the next stream from 2.2.2.2
It seems the script below would do what I am looking for:
#!/bin/bash
/usr/bin/ffmpeg -i 'http://1.1.1.1/soft_music' -vn -ar 8000 -ac 1 -f s16le - & echo $! > /tmp/my_pid
%1
/usr/bin/ffmpeg -i 'http://2.2.2.2/soft_music' -vn -ar 8000 -ac 1 -f s16le - & echo $! > /tmp/my_pid
%1
What this does is put the ffmpeg process into the background just for one moment to store the PID in a file. As soon as it goes to the next line we recover it with the job ID which will be 1.
Shell Scripting:
I am doing some testing on my router, I am using mdk3 and reaver utility for that.
here are the two commands:
[cmd1] echo y|reaver -i wlan2mon -b 00:FF:EE:CC:DS:B6 -vv -l 230
[cmd2] sudo mdk3 wlan2mon a -a 00:FF:EE:CC:DS:B6
goal:
I am trying to create a shell script which will run [cmd1] for 2 minutes, then it will send the ctrl + c signal to [cmd1] so that it will save the reaver session.
then cmd2 will run for 2 minutes and this will also stop after that.
these two will be in loop.
below is the sample script which I written can you add timer to it..?
#!/bin/bash
while :; do echo
echo "running mdk for 2 minutes";
timeout 120 sudo mdk3 wlan2mon a -a 00:FF:EE:CC:DS:B6;
echo "mdk finished";
echo "starting reaver for 2 minutes ";
#here timeout won't work, as ctrl+c can only save the state.
//add code here to run reaver utility for two minutes and send ctrl+c to it
echo y|reaver -i wlan2mon -b 00:FF:EE:CC:DS:B6 -vv;
echo "reaver ran for two minutes";
done
I'm not familiar with the reaver program, but I think the following should work,
# Run reaver as a background process (add &)
echo y|reaver -i wlan2mon -b 00:FF:EE:CC:DS:B6 -vv &
# Save the process id.
reaverpid=$!
# Sleep 2 minutes
sleep 120
# Send SIGINT, which is what ctrl-c normally does.
kill -SIGINT $reaverpid
I'm creating a sh script on my raspberry for a timelapse.
I've included in the script 4 command that will successively take place, each command tested and working. Now my question is: how to come back to the first command after the last one, indefinitely?
#!/bin/bash
sudo raspistill -w 1024 -h 768 -o /home/pi/timelapse/a%04d.jpg -t 600000 -tl 30000
sudo kill $(ps ax | grep 'timelapse' | awk '{print $1}')
sudo avconv -r 10 -i /home/pi/timelapse/a%04d.jpg -r 10 -vcodec libx264 -crf 20 -g 15 timelaps$
sudo rm /home/pi/timelapse/*.jpg
So after sudo rm /home/pi/timelapse/*.jpg I want to go back to the first command.
Would you have any idea?
thanks.
You can use a loop:
#!/bin/sh
while true; do
...
done
or, re-invoke the script:
#!/bin/sh
...
exec $0 "$#"
Frankly, either one of these seems risky in your case since you're doing no error checking at all, and you run the risk of entering a relatively fast loop of commands continuously failing. At the very least, you should pause for a bit by using while sleep 1; instead of while true;