How to automatically export track of narrated text (KJV Proverbs with 581 labels) so that to each label can be added the same background music
So far I added background music track and I already done multiple export 581 mp3s. Each of them consist of 1 second music, then narrated text and then again music. There is no Fade Up and Fade Down. Also music is from the middle of the song. This is not hearing very good.
In each mp3 music should start approx 10 seconds before narrated text and ended after approx 10 seconds after end of narrated text with Fade Down. Background music for all labels should be the same.
I believe this can be achieved with macros. I hope so.
Thanks for your response. I tried to do everything in Audacity, (I know this is Audacity forum) but code in DOS can explain more.
Code in DOS works. But only for one file, because I can not use SET Inside FOR loop.
Then I started with PowerShell, but I do not know how to continue…
So far I exported 581 mp3’s from 2+ hour of narrated text. Now I want to add some silence before and some silence at the and of each MP3.
And in every MP3 would like to add background music with FadeIn and Fade Out.
If there were 10 MP3 files, I would do this without any script. But 581 MP3 files got me worried.
@echo off
setlocal EnableDelayedExpansion
SET "FFMPEG=c:\Osebno\SavliM86\util\ffmpeg\bin\ffmpeg.exe"
SET "ffprobe=c:\Osebno\SavliM86\util\ffmpeg\bin\ffprobe.exe"
SET "input=working"
SET "SilenceBefore=4"
SET "SoundBefore=1"
SET "SilenceAtEnd=10"
del /Q _*.mp3 >nul 2>&1
REM Loop for all SloKJV*.mp3 files in map
for /R %%f in (SloKJV*.mp3) do (
SET /a "duration=0" & echo Duration should be zero but SET in FOR loop is not working in CMD: !duration!
REM Make few seconds of silence at the begining of the mp3
%ffmpeg% -y -loglevel panic -i %%f -af "adelay=%SilenceBefore%s:all=true" !input!_.mp3
REM Make few seconds of silence at the end of the mp3
%ffmpeg% -y -loglevel panic -filter_complex aevalsrc=0 -t %SilenceAtEnd% Silence.mp3
%ffmpeg% -y -loglevel panic -i "concat:!input!_.mp3|Silence.mp3" -c copy !input!__.mp3
ECHO !%%f!
REM Calculate new lenhgt of MP3
for /F "delims=" %%I in ('%ffprobe% -v error -show_entries format^=duration -of default^=noprint_wrappers^=1:nokey^=1 %%f 2^>^&1') do
set "duration=%%I"
echo Duration je: !duration1!
REM Removes dot and decimal numbers
for /f "tokens=1 delims=." %%a in ('echo %duration%') do set "duration1=%%a"
echo Duration1 is: !duration1!
REM How much time after mp3 music can be heard
Koliko casa po govorjenju pregovora se se slisi muzika
SET /a "lenght=!duration1!+%SilenceAtEnd%"
echo Lenght je: !lenght!
REM When start to VolDown to the nul.
SET /a "WhenVolDown=!duration1!-5"
echo WhenVolDown: !WhenVolDown!
REM Compine to MP3 in to one MP3
%ffmpeg% -y -loglevel panic -i !input!__.mp3 -i hill.mp3 -filter_complex amix=inputs=2:duration=shortest !input!___.mp3
REM Add FadeIn and FadeOut
%ffmpeg% -y -loglevel panic -i !input!___.mp3 -af "afade=t=in:st=0:d=%SoundBefore%,afade=t=out:st=%WhenVolDown%:d=5" !input!____.mp3
echo %%f
REM Vol Up for entire MP3
%ffmpeg% -y -loglevel panic -i !input!____.mp3 -filter:a "volume=3" %%f.mp3
del /Q _*.mp3 >nul 2>&1
)
I started even in PowerShell
Set-ExecutionPolicy RemoteSigned
Set-Variable -Name "FFMPEG" -Value "c:\Osebno\SavliM86\util\ffmpeg\bin\ffmpeg.exe"
Set-Variable -Name "ffprobe" -Value "c:\Osebno\SavliM86\util\ffmpeg\bin\ffprobe.exe"
Set-Variable -Name "input" -Value "working"
Set-Variable -Name "SilenceBefore" -Value "4"
Set-Variable -Name "SoudBefore" -Value "1"
Set-Variable -Name "SilenceAtEnd" -Value "10"
# remove _*.mp3 files
Remove-Item -Path C:\Temp\_pregovori\_*.mp3 -Force
# Make few seconds of silence at the begining of the mp3
&$ffmpeg -y -loglevel panic -i SloKJV_Pregovori-01.mp3 -af "adelay=4s:all=true" working.mp3
# Make few seconds of silence at the end of the mp3
&$ffmpeg -y -loglevel panic -filter_complex aevalsrc=0 -t 20 Silence.mp3
# $ArgumentList = '-y -loglevel panic -i "concat:working.mp3|Silence.mp3" -c copy working_.mp3'
foreach ($i in Get-ChildItem .\*.mp3) {echo "file '$i'" >> list.txt}
&$ffmpeg -y -f concat -safe 0 -i file:list.txt -c copy working_.mp3
# -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4
# Calculate new lenhgt of MP3
# do (set "duration=%%I")'
&$ffprobe -v error -show_entries format^=duration -of default^=noprint_wrappers^=1:nokey^=1 SloKJV_Pregovori-01.mp3
# ....
You have a folder full of short MP3 files (581 files). I shall refer to these as the “input files”.
Fine.
The input files vary in length between 10 seconds and 20 seconds duration.
For future use length will vary between 9 seconds and 5*60=300 seconds. There will another narrations coming.
You have one background music file. I shall refer to this as the “BGM” file.
Yes. But for future versions we might replace it with other BGM.
You want the output files to be the full length of the background music file.
Rather no. After narration + some time 15-20 seconds BGM should fade out in 5 seconds…
You want the BGM to fade in at the start and fade out at the end
Yes. Fade in and fade out should be 5 seconds at beginning and at the end.
You want the “input file” to be placed near the middle of the BGM.
Rather near the start. Input file should be at cca 10 seconds after start.
You want the BGM to be lower volume (or silent?) while the “input file” plays
Lower. So the narration can be heard.
This point is important for how we approach the task.
If you need different BGM for each “input” file, then the task is not possible with Macros.
If we are using one BGM file, then I think we can create a Macro to automate the task. The BGM file could be replaced in the future, but still just one BGM file when running the Macro on multiple “input” files.
Would it be correct to say that you want:
10 seconds BGM, of which the first 5 seconds fades in,
followed by the “input” mixed with BGM (BGM at a lower volume),
followed by 15 seconds of BGM (original volume), of which the final 5 seconds fades out
I’m surprised nobody addressed the “sloppy MP3” problem. MP3 files do not have firm, fixed, reliable stop and start times. They wander making it a nightmare to do accurate production with them. Didn’t you run into that when you did them manually? Where you put the sound and where it ended up are frequently different.
Or maybe you did run into the error, but it was buried in other errors, or you just didn’t recognize it. That may be another reason you can’t automate this.
If we are using one BGM file, then I think we can create a Macro to automate the task. The BGM file could be replaced in the future, but still just one BGM file when running the Macro on multiple “input” files.
There will be only one GBM for all BGM 581 files,
10 seconds BGM, of which the first 5 seconds fades in,
followed by the “input” mixed with BGM (BGM at a lower volume),
followed by 15 seconds of BGM (original volume), of which the final 5 seconds fades out
Yes. Exactly.
I’m surprised nobody addressed the “sloppy MP3” problem. MP3 files do not have firm, fixed, reliable stop and start times. They wander making it a nightmare to do accurate production with them. Didn’t you run into that when you did them manually? Where you put the sound and where it ended up are frequently different.
Or maybe you did run into the error, but it was buried in other errors, or you just didn’t recognize it. That may be another reason you can’t automate this.
I’ve got some errors during ffmpeg combine two MP3 files. But final mp3 works on my devices. So I was not worried about that.
That’s true, but I don’t expect it to be a problem in this case. Once the file has been imported into Audacity it has an exact and precisely defined length (in samples).
One issue that we can’t avoid is that if the voice recordings are MP3, and the final output files are MP3, then there will be some amount of sound quality loss. Provided that the kbps setting is not too low, then I’m not expecting this to be a major problem.
I’ll get back to you on this when I’ve had time to try out some things in Macros - hopefully within the next couple of days.
I’m not sure what you are showing me. Is each clip one “input” file, or do you want each labelled section to be an “input” file?
If you want to treat each labelled section as an input file, then you will need to use “Export Multiple” to export each labelled section as a separate file.
This is the Macro script that I’ve come up with.
The line to pay attention to is the “Import2:” command.
This points to the BGM track, which in my case (on Linux) is the file: “/home/steve/Desktop/temp/bgm/bgm.wav”
On Windows the file name will be something like (depending on where your BGM file is):
“C:\Users\msavli\Documents\bgm.wav”
Important: The BGM file must be at least 25 seconds longer than the longest input file (10 seconds before and 15 seconds after).
Important: The BGM file must NOT be included in the files that you select for batch processing - I’d suggest putting it in a different folder so that you don’t select it by accident when running the Macro.
If you are unsure what to do with this code, just ask and I’ll explain.
SelectAll:
Cut:
Select:End="100" Mode="Set" RelativeTo="ProjectStart" Start="10"
Paste:
Import2:Filename="/home/steve/Desktop/temp/bgm/bgm.wav"
SelectAll:
NyquistPrompt:Command=";type process\n;version 4\n\n;; Trim tracks to \"outro\" seconds beyond end of first track.\n(setf outro 15.0)\n(setf prop-id 'outrotrim120920201148) ;unique property id\n\n;ensure that *scratch* is clean on first track\n(when (= (get '*track* 'index) 1)\n (remprop '*scratch* prop-id))\n\n(defun trim (sig end)\n ;; Trim track to end at 'end'\n (if (arrayp sig)\n (vector (extract-abs 0 end (aref sig 0))\n (extract-abs 0 end (aref sig 1)))\n (extract-abs 0 end sig)))\n\n(let ((saved-dur (get '*scratch* prop-id)))\n (cond\n (saved-dur ; property already saved\n (when (= (get '*track* 'index)\n (length (get '*selection* 'tracks)))\n (remprop '*scratch* prop-id))\n (trim *track* (+ saved-dur outro)))\n (t (putprop '*scratch* (get '*track* 'end-time) prop-id)\n \"\")))\n" Parameters="" Version="4"
LastTrack:
TrackMoveUp:
SelectAll:
SelectTracks:Mode="Set" Track="0" TrackCount="1"
AutoDuck:DuckAmountDb="-12" InnerFadeDownLen="0" InnerFadeUpLen="0" MaximumPause="1" OuterFadeDownLen="0.5" OuterFadeUpLen="0.5" ThresholdDb="-30"
Select:Start="0" End="5"
FadeIn:Use_Preset="<Factory Defaults>"
Select:Start="0" End="5" RelativeTo="ProjectEnd"
FadeOut:Use_Preset="<Factory Defaults>"
Select:Start="0" End="0"
ExportWav:
I’m not sure what you are showing me. Is each clip one “input” file, or do you want each labelled section to be an “input” file?
From this File I got all these 581 mp3’s. Each of them has its own label.
Yes I’ve got them with “Export Multiple”
With little googling I’ve put your macro in c:\Users\msavli\AppData\Roaming\audacity\Macros\ directory.
Uau. This code works I as expected. Maybe a little tuning of volume, but I think I can handle that.
It there a way to combine these two macros “Export Multiple” and your script?
Every Label in my project file and through “Export Multiple” every MP3 has it’s own metatags.
Since I’ve put 581-times effort to set up each label, can this metatags be preserved in exported WAV? (see picture)
Because now BGM metatags are preserved.
Since I’ve got permission from the band, BGM Song name can be preserved from GBM file in one of the fields.
SelectAll:
Cut:
Select:End="100" Mode="Set" RelativeTo="ProjectStart" Start="10"
Paste:
Import2:Filename="/home/steve/Desktop/temp/bgm/bgm.wav"
SelectAll:
NyquistPrompt:Command=";type process\n;version 4\n\n;; Trim tracks to \"outro\" seconds beyond end of first track.\n(setf outro 15.0)\n(setf prop-id 'outrotrim120920201148) ;unique property id\n\n;ensure that *scratch* is clean on first track\n(when (= (get '*track* 'index) 1)\n (remprop '*scratch* prop-id))\n\n(defun trim (sig end)\n ;; Trim track to end at 'end'\n (if (arrayp sig)\n (vector (extract-abs 0 end (aref sig 0))\n (extract-abs 0 end (aref sig 1)))\n (extract-abs 0 end sig)))\n\n(let ((saved-dur (get '*scratch* prop-id)))\n (cond\n (saved-dur ; property already saved\n (when (= (get '*track* 'index)\n (length (get '*selection* 'tracks)))\n (remprop '*scratch* prop-id))\n (trim *track* (+ saved-dur outro)))\n (t (putprop '*scratch* (get '*track* 'end-time) prop-id)\n \"\")))\n" Parameters="" Version="4"
LastTrack:
TrackMoveUp:
SelectAll:
SelectTracks:Mode="Set" Track="0" TrackCount="1"
AutoDuck:DuckAmountDb="-12" InnerFadeDownLen="0" InnerFadeUpLen="0" MaximumPause="1" OuterFadeDownLen="0.5" OuterFadeUpLen="0.5" ThresholdDb="-30"
Select:Start="0" End="5"
FadeIn:Use_Preset="<Factory Defaults>"
Select:Start="0" End="5" RelativeTo="ProjectEnd"
FadeOut:Use_Preset="<Factory Defaults>"
Select:Start="0" End="0"
ExportWav:
No. Export Multiple is not currently supported by macros.
You will need to create your individual “input” files first, then apply the macro to the files.
I’m not sure how many files the macro can handle in one go. I’d suggest that you try it on just a few at first, then gradually increase the number. It “may” be able to handle all 581 files in one go, but macros have a habit of failing with very large batches of files.
Export Multiple allows you to name the files based on the label names (ensure that you avoid characters that are not allowed in file names).
You will need to create your individual “input” files first, then apply the macro to the files.
I’m not sure how many files the macro can handle in one go. I’d suggest that you try it on just a few at first, then gradually increase the number. It “may” be able to handle all 581 files in one go, but macros have a habit of failing with very large batches of files.