How do I add RIFF header to MP3 files programatically? - linux

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.

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
)

Syntax error: "(" unexpected -- with !(*.sh) in bash script [duplicate]

This question already has answers here:
Difference between sh and Bash
(11 answers)
Closed 29 days ago.
I want to run a sh file:
#!/bin/bash
for f in !(*.sh); do
ffmpeg -i "$f" -vf yadif=0:-1 -threads 0 -c:v libx264 -pix_fmt yuv420p \
-r 29.97 -b:v 3000k -s 1280x720 -preset:v slow -profile:v Main \
-level 3.1 -bf 2 -movflags faststart /mnt/media/out-mp4/"${f%.mxf}.mp4"
rm $f
done
However, I get the following error:
2: task1.sh: Syntax error: "(" unexpected
If I try directly on the command line it works perfectly.
the path and permissions are already reviewed
Any idea what might be happening?
This is not a "sh file" -- it's a bash script. If you run it with sh yourscript, it will not work (as extglobs, the shell feature you're trying to use, aren't supported in POSIX sh); it needs to be run only with bash yourscript, or with ./yourscript when starting with #!/bin/bash (as it does). Describing it as a "sh file" is thus misleading. Moreover, even with bash, the extended globbing feature needs to be turned on.
Your immediate issue is that !(*.sh) is not regular glob syntax; it's an extglob extension, not available by default. You may have a .bashrc or similar configuration file which enables this extension for interactive shells, but that won't apply to scripts. Run:
shopt -s extglob
...to enable these features.
Cleaned up, your script might look like:
#!/bin/bash
shopt -s extglob
# putting settings in an array allows unescaped newlines in definition
# also sorted to make it easier to find things.
settings=(
-b:v 3000k
-bf 2
-c:v libx264
-level 3.1
-movflags faststart
-pix_fmt yuv420p
-preset:v slow
-profile:v Main
-r 29.97
-s 1280x720
-threads 0
-vf yadif=0:-1
)
for f in !(*.sh); do
ffmpeg "${settings[#]}" -i "$f" \
/mnt/media/out-mp4/"${f%.mxf}.mp4" && rm -- "$f"
done
Note the following changes, above and beyond formatting:
shopt -s extglob is on its own line, before the glob is expanded.
The rm is only run if ffmpeg succeeds, because the separator between those commands is &&, rather than either ; or a bare newline.
The -- argument passed to rm tells it to treat all future arguments (in this case, the content of "$f") as a filename, even if it starts with a dash.
The "$f" argument to rm is inside double quotes.
You need to enable the extended globbing in the script:
shopt -s extglob
Also make sure you're not running the script in a different script, e.g. by calling sh script.sh.
I thing you are running this script sh code.sh. This means you are using sh to run the script, but the first line (#!/bin/bash) implies it's been written for bash.
On some systems sh and bash are the same, but on others they are not; and, when invoked as sh, Bash turns off some non-POSIX features. So it's important to use the right shell and the right invocation.
Use bash code.sh or better still, make the script executable (chmod a+x code.sh) and then run it directly (./code.sh)

ffmpeg concatenate with dynamic chunks

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?

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

Linux Script - Extension retained

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

Resources