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.
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 execute the command in Ubuntu to cut a video:
/usr/bin/ffmpeg -i video.mp4 -an -ss 00:00:1 -t 00:00:08 -async 1
In Windows 10 its work, but not work in Ubuntu.
I receive in Ubuntu the warning:
Trailing options were found on the commandline.
and receive the error:
At least one output file must be specified
What do I do?
do:
ffmpeg -i video.mp4 -ss 00:00:01 -t 00:00:08 -async 1 cut.mp4
just add output file name, in this situation - cut.mp4
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.
I have a shell script that takes a directory as input, reads all mp4 files in it and convert them to a mp3 with ffmpeg:
#!/bin/bash
dir=$1
while read -rd "" file
do
base=$(basename "$file")
filename=${base%(*}".mp3"
ffmpeg -i "$file" -vn -ar 44100 -ac 2 -ab 192000 -f mp3 "$filename" &
done < <(find $dir -maxdepth 1 -iname "*.mp4" -print0)
wait
exit 0
Currently all these calls to ffmpeg are forked because when I leave out the & at the end only the first file in converted and the others are ignored.
But this is problematic because somethings this fails on some files error messages like the following:
path/to/file/file name - with spaces(info)(temp_information).mp4: No such file or directory
All file names normally contain spaces, maybe that is the reason why it fails for some files.
Thus, I have the following questions:
When I don't fork the ffmpeg calls why is only the first file executed? I expected that the loop waits until the process is finished and then continues with the next iteration.
Why is the script unable to find some files (maybe it is a problem of ffmpeg)?
How to solve all these problems and make the script to work?
You are not acknowledging stdin
ffmpeg -i "$file" -blah -blah -nostdin "$filename" &
shell script ffmpeg stops after 2 jobs
To answer the comment:
You should not be forking anyway, FFmpeg already runs in multiple threads to maximize CPU, and you might even suffer
from thrashing
by forking it.