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
)
Related
#!/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.
I have a list of mp3 files and i want to set all mean_volume to the same db value using a script, so I enter the command for detecting the value (https://trac.ffmpeg.org/wiki/AudioVolume) and I try to grep the value but it fails and instead prints all the output from the ffmpeg command. Any thoughts?
Also tried tr instead of grep. The command I used is:
ffmpeg -i sample.mp3 -filter:a volumedetect -f null /dev/null | grep 'mean_volume'
ffmpeg console output is stderr, so you need to redirect to stdout:
ffmpeg -i input.mp3 -filter:a volumedetect -f null - 2>&1 | grep mean_volume
or for Bash 4+:
ffmpeg -i input.mp3 -filter:a volumedetect -f null - |& grep mean_volume
Result:
[Parsed_volumedetect_0 # 0x564635d62800] mean_volume: -22.6 dB
If you just want the value use awk:
ffmpeg -i input.mp3 -filter:a volumedetect -f null - |& awk -F': ' '/mean_volume/ {print $2}'
Result:
-22.6 dB
The ffmpeg docs for concat lists the following way
ffmpeg -f concat -i mylist.txt -c copy output
The mylist.txt file contains file like
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
What I am looking is for a way to do this concat in a persistent way where the number of files can keep increasing, for example in livestreaming
I will be sending chunks of video (mp4 files) of 10 seconds each to my server and want to concat/stitch them together to output to a RTMP stream (for livestreaming)
If concat is not the proper way to do this, please suggest alternatives.
Really interested to know how people use the above concept (I hope its how it works) to send video chunks from mobile device for livestreaming
The ffmpeg docs have an example that does exactly what you're asking: https://trac.ffmpeg.org/wiki/Concatenate
This is their example:
#!/bin/bash
fn_concat_init() {
echo "fn_concat_init"
concat_pls=`mktemp -u -p . concat.XXXXXXXXXX.txt`
concat_pls="${concat_pls#./}"
echo "concat_pls=${concat_pls:?}"
mkfifo "${concat_pls:?}"
echo
}
fn_concat_feed() {
echo "fn_concat_feed ${1:?}"
{
>&2 echo "removing ${concat_pls:?}"
rm "${concat_pls:?}"
concat_pls=
>&2 fn_concat_init
echo 'ffconcat version 1.0'
echo "file '${1:?}'"
echo "file '${concat_pls:?}'"
} >"${concat_pls:?}"
echo
}
fn_concat_end() {
echo "fn_concat_end"
{
>&2 echo "removing ${concat_pls:?}"
rm "${concat_pls:?}"
# not writing header.
} >"${concat_pls:?}"
echo
}
fn_concat_init
echo "launching ffmpeg ... all.mkv"
timeout 60s ffmpeg -y -re -loglevel warning -i "${concat_pls:?}" -pix_fmt yuv422p all.mkv &
ffplaypid=$!
echo "generating some test data..."
i=0; for c in red yellow green blue; do
ffmpeg -loglevel warning -y -f lavfi -i testsrc=s=720x576:r=12:d=4 -pix_fmt yuv422p -vf "drawbox=w=50:h=w:t=w:c=${c:?}" test$i.mkv
fn_concat_feed test$i.mkv
((i++));
echo
done
echo "done"
fn_concat_end
wait "${ffplaypid:?}"
echo "done encoding all.mkv"
I try to concatenate several webm files with command below and it works (in my case)
ffmpeg -i chunk.1.webm -i chunk.2.webm -i chunk.3.webm -i chunk.4.webm -filter_complex "[0:0] [1:0] [2:0] [3:0] concat=n=4:v=1:a=0 [v]" -map "[v]" filter.webm -y
Using ffmpeg to combine small mp4 chunks?
I'm a newbie to linux scripting and am having an issue with a script that I got from the web and am trying to modify.
Here is the script
#!/bin/bash
if (($# ==0))
then
echo "Usage: flvto3gp [flv files] ..."
exit
fi
while (($# !=0 ))
do
ffmpeg -ss 00:00:10 -t 1 -s 400x300 -i $1 -f mjpeg /home/zavids/rawvids/thumbs/$1.jpg
shift
done
echo "Finished"
echo "\"fakap all those nonsense!\""
echo ""
So I'm grabbing a screenshot from a video and saving it as a jpeg. The problem is the extension of the video file is retained so finished file is video.flv.jpg (for example). How can I get rid of that video extension?
Change this line
ffmpeg -ss 00:00:10 -t 1 -s 400x300 -i $1 -f mjpeg /home/zavids/rawvids/thumbs/$1.jpg
to this
ffmpeg -ss 00:00:10 -t 1 -s 400x300 -i $1 -f mjpeg /home/zavids/rawvids/thumbs/${1%.*}.jpg
That strips the extension from the input file before using it to create the name of the output file, using bash parameter expansion.
You can try to use this :
${string%substring}
It deletes shortest match of $substring from back of $string.
For your case :
${1%.flv}
This code will substitute .flv from the end of your first argument.
You can have a lot of details here too : http://tldp.org/LDP/abs/html/string-manipulation.html
More information about what I want to do here; http://www.studiodust.com/riffmp3.html
I want a way so that my control panel (made with Perl and Webmin) can do this automatically. Right now I have to rely on system calls and have a binary for Linux. Is there a library that does it for Perl or some other language?
What's the best way of doing this?
I know nothing about RIFF files or their structure, uses, etc. But did you try searching CPAN? The first result looks pretty promising.
The website I reference had the answer I needed. I didn't know they made a linux variant.
I have the following script for the exact thing you asked about.
#!/bin/bash
echo "$1"
ffmpeg -y -i "$1" -f wav out.wav > /dev/null 2>&1 && \
normalize-audio -q out.wav && \
lame --silent -a -m m --cbr -b 64 -q 0 out.wav out.mp3 && \
ffmpeg -y -i out.mp3 -f wav -acodec copy "$1" > /dev/null 2>&1 && \
echo "done."
rm out.wav out.mp3
Just edit the parameters to lame or just use the ffmpeg call and you're set.