Script bash to compress .mp4 with subfolders and another destination folder - bash

I'm trying to create a script to convert all .mp4 videos into subfolders.
My hierarchy is :
Folder_1/
Videos_encoded/
Videos_orig/
first-video.mp4
video_2/
video-in-folder-video_2.mp4
I want to compress all .mp4 (with into subfolders) are in the Videos-orig/ to the videos_encoded as the destination folder.
I tried :
find /home/user/Folder_1/videos_orig/ -type d | while read ligne
do
cd "$ligne"
for i in *.mp4;
do
ffmpeg -y -i "$i" -ar 44100 -c:v libx265 -b:v 1000 -c:a mp3 -b:a 128k /home/user/Folder_1/videos_encoded"$(basename "${i/.mp4}").mp4"
done
done
But I have the error message : **.mp4 no such file or directory* (result of ffmpeg command).
I don't understand ...
There is it a better way to perform this project ?
Thanks you very much in advance for your help :)
Regards

If not preserving the directory structure in the output is fine, I think this example would be sufficient by solely using find with -exec
find orig/ -type f -name "*.mp4" -exec sh -c 'ffmpeg -i "{}" "encoded/$(basename {})"' \;

The command works, but it doesn't compress all of my files.
My command line :
find /volume1/Master_1/Unites_communes/No_compressed/ -type f -name "*.mp*" -exec sh -c 'ffmpeg -n -i "{}" -crf 23 -ar 44100 -c:v libx264 -b:v 1000 -c:a mp3 -b:a 128k "/volume1/Master_1/Unites_communes/Cours_videos/$(basename {})"' \;
I run :
find /volume1/Master_1/Unites_communes/No_compressed/ -type f -name "*.mp4" -print
and I have :
Sortie standard/erreur :
/volume1/Master_1/Unites_communes/No_compressed/2017-10-13_131756.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-23_132120.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-24_090340.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-24_131336.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-25_085744.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-25_131357.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-26_133340.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-27_083836.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-27_133906.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-13_090642.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-10_125731.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-10_090037.mp4
/volume1/Master_1/Unites_communes/No_compressed/2017-10-04_140230.mp4
Total : 13 Files
In the destination I have only 7 files compressed and that it.
I have a problem in my ffmpeg command ?
I'm on a Synology, if it can help you.

Related

Change ffmpeg output directory

Im using ffmpeg to compress footage and i want to compess the footage of a specific day but when i overwrite the files it outputs a empty stream because it writes as it reads at the same time so i want to rename the output file. Find will give the full path which is necessary but i don't know how to change the actual file name, rather than the path.
Any suggestions?
find /home/server/recordings/compress -name '*.mp4' -print0 | xargs -0 -I{} ffmpeg -i {} -c:v libx265 -preset fast -crf 25 -x265-params "vbv-maxrate=1500:vbv-bufsize=1000" -c:a aac {}
The last argument in ffmpeg is the output filename. So you can change your command to
find /home/server/recordings/compress -name '*.mp4' -print0 | xargs -0 -I{} ffmpeg -i {} -c:v libx265 -preset fast -crf 25 -x265-params "vbv-maxrate=1500:vbv-bufsize=1000" -c:a aac {}.out
This way all the output files will have .out appended.
Pass file names to sh using -exec and modify the filename there. For example:
find /home/server/recordings/compress -name '*.mp4' -exec sh -c '
ffmpeg -i "$1" -c:v libx265 -preset fast -crf 25 -x265-params "vbv-maxrate=1500:vbv-bufsize=1000" -c:a aac \
"${1%/*}/modified_${1##*/}"
' _ {} \;

recursively convert files using ffmpeg in parallel

I have the following two commands:
parallel --eta ffmpeg -loglevel 0 -i {} -c:a aac -b:a 64k {.}.aac ::: *
that converts all files (audio) in current folder to aac format in parallel (file.mp3>file.aac), and
find . -type f -not -name "*.jpg" -exec bash -c 'ffmpeg -loglevel 0 -i "{}" -c:a aac -b:a 64k "{}".aac' \;
that converts all files in all subdirectories to aac format (file.mp3>file.mp3.aac), but not in parallel.
So I want to accomplish two things:
execute command 2 in parallel
that the result is saved as in command 1, ie, file.mp3>files.aac instead of file.mp3>file.mp3.aac.
I've tried some combinations but they didn't work.
OK,
I think I finally got it like this:
find . -type f -not -name "*.jpg" -not -name "*.png" -not -name "*.aac" -print0 | parallel -0 --eta ffmpeg -loglevel 0 -i {} -c:a aac -b:a 64k {.}.aac

How would i create a bash script to convert .wav files from folder [A] to mp3 format . then move them to new folder [mp3folder]

I want this Script to run in a loop every hour. The main goal is to convert the wav files that I export to my VM share folder when using Ableton.
Messy Idea of what I want but need lots of help with
for file in /mnt/hgfs/VMshare/transfer/*
do
if ["$file" == "/mnt/hgfs/VMshare/transfer/*.wav]
then
find -name "*.wav" -exec ffmpeg -i {} -acodec libmp3lame -ab 128k {}.mp3 \;
else
echo "NO WAV TO CONVERT"
mv /mnt/hgfs/VMshare/transfer/*.mp3 /root/Desktop/MP3Music/
Change the FILE_PATH variable, destination path and ffmpeg command as per your need. This worked for me.
#!/bin/bash
FILE_PATH=/path/to/wav/format/files/*.wav
for FILE in `ls $FILE_PATH`
do
BASENAME=`basename $FILE`
ffmpeg -i $FILE -vn -ar 44100 -ac 2 -ab 192k -f mp3 `dirname "${FILE}"`/${BASENAME%.wav}.mp3 > /dev/null 2>&1
mv `dirname "${FILE}"`/${BASENAME%.wav}.mp3 /path/to/destination/
done
OR
Single command:
find /path/to/wav/files/ -name "*.wav" -type f | xargs -I {} ffmpeg -i {} -vn -ar 44100 -ac 2 -ab 192k -f mp3 {}.mp3
But the above stores the output files as *.wav.mp3, you may need to rename it while moving to destination path.

Recursively re-encode .mp4 files to new copies of .mp4 and convert .mp4 to .webm and .ogg using ffmpeg

I have about 300 videos in .mp4 files that I need re-encode as new .mp4 files and to convert them to .webm and .ogg files.
I want to do it at the command line using ffmpeg, and I have the following command that converts the .mp4 into a .webm.
find ./ -name '*.mp4' -exec bash -c 'ffmpeg -i "$0" -vcodec libvpx -acodec libvorbis -cpu-used 5 -threads 8 "${0%%.mp4}.webm"' {} \;
Can someone help me modify this command to two separate commands, one for .mp4 -> .mp4 (suffixing the filename with -2) and another for .mp4 -> .ogg?
Thank you.
Well, as I didn't get any replies, I did find the answer myself.
So, for the benefit of others looking to do the same thing, here are the various commands I put together:
webm
find ./ -name '*.mp4' -exec bash -c 'ffmpeg -i "$0" -vcodec libvpx -acodec libvorbis -vf scale=-1:480 -cpu-used 5 -threads 8 "${0%%.mp4}.webm"' {} \;
ogv
find ./ -name '*.mp4' -exec bash -c 'ffmpeg -i "$0" -vcodec libtheora -acodec libvorbis -vf scale=-1:480 -cpu-used 5 -threads 8 "${0%%.mp4}.ogv"' {} \;
flv
find ./ -name '*.mp4' -exec bash -c 'ffmpeg -i "$0" -c:v libx264 -ar 22050 -crf 28 -vf scale=-1:480 -cpu-used 5 -threads 8 "${0%%.mp4}.flv"' {} \;
mp4
find ./ -name '*.mp4' -exec bash -c 'ffmpeg -i "$0" -vcodec libx264 -vf scale=-1:480 -cpu-used 5 -threads 8 "${0%%.mp4}-2.mp4"' {} \;
jpg
find ./ -name '*.mp4' -exec bash -c 'ffmpeg -i "$0" -ss 00:00:10 -vframes 1 -r 1 -vf scale=-1:480 -f image2 "${0%%.mp4}.jpg"' {} \;
Note that I have added the flag -vf scale=-1:480 which scales the video proportionately. I have set the height to 480px and the width is automatically calculated.
Also, note that I have also included a screenshot export from each video. The capture is made at the 10th second of the video and is saved as a jpeg file.
If you would like to retain the dates of the original files so that the new version (.webm, .ogv, .mp4, .flv) have the same modification dates, you can use the touch command as follows:
touch -r oldfile newfile

Issue with overwriting file while using ffmpeg for converting

I'm using ffpmeg to convert all my videos to mp4:
ffmpeg -i InpuFile -vcodec h264 -acodec aac -strict -2 OutputFile.mp4
The problem is, if I'm overwriting the input file, i.e the output and input files are the same:
ffmpeg -i InpuFile -vcodec h264 -acodec aac -strict -2 InpuFile.mp4 -y
or
ffmpeg -i InpuFile -y -vcodec h264 -acodec aac -strict -2 InpuFile.mp4
the new file is not good. He lasts one second and his size is extremely small.
Any ideas?
I want to use this as a script in my server so the overwriting is the most convinient way for me, I prefer that way instead of creating temporary files then replacting the temporary with original.
I had this same (frustrating) problem, you may have noticed that this happens because ffmpeg is writing over the file that it's reading, you are corrupting the source before the process finish... ffmpeg doesn't put the file in some buffer, so you can't do this way, you will have to use a temporary file.
just in case
You cannot overwrite the input file while you are encoding. You must encode to an different output file.
Afterwards, you can replace the original file with the new encoded file.
As others have mentioned, there is no way to do this without creating a temp file. You mentioned that you wanted to compress all your videos, and for it to be convenient. Here is a bash one-liner I used to compress all MP4 & MOV inside a directory:
find * -type f \( -iname \*.mp4 -o -iname \*.mov \) -execdir ffmpeg -i {} -vcodec libx265 -crf 24 temp_{} \; -execdir mv temp_{} {} \;
The -crf param controls the video bitrate. It's value ranges from 18-24, lower value is higher bitrate.
If you just wanted to compress .mp4 for example then you'd change the command to:
find * -type f -iname "*.mp4" -execdir ffmpeg -i {} -vcodec libx265 -crf 24 temp_{} \; -execdir mv temp_{} {} \;
Hope this helps OP, or anyone looking to do something similar.
Neither is too annoying tmp file use. In one line:
input="InpuFile"; ffmpeg -i "$input" -y -vcodec h264 -acodec aac -strict -2 "/tmp/$input";rm "$input"; mv "/tmp/$input" .;

Resources