Go Back   Cockos Incorporated Forums > REAPER Forums > REAPER Q&A, Tips, Tricks and Howto

Reply
 
Thread Tools Display Modes
Old 04-16-2015, 03:28 PM   #1
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default Looking way to automate batch rendering process

I had a previous thread about this, but I wasn't particularly clear about how I had things set up so I wanted to make sure this post included all the particulars and what I'm trying to accomplish.

I do a weekly radio show and it needs to have unique portions for certain stations (call sign, etc). For this reason I have a common voice track which contains generic items (show title, etc), and then other tracks that contain station-specific audio. This is my track configuration:

1: master (fx: limiter)
2: music (fx: leveler & compressor with sidechain from 3 to duck music)
3: PARENT combined voice track (fx: compressor)
4: -CHILD: voice track common to all stations.
5: -CHILD: station-specific voice track (KTKE)
6: -CHILD: station-specific voice track (KKJZ)
7: -CHILD: station-specific voice track (web)
8: -CHILD: ...

So track 2 contains the music that plays throughout the entire show. Track 3 sums and compresses all the child voice tracks and also sends a sidechain output to track 2 to duck the music. The reason for track 4 and the subsequent station-specific voice tracks is I do the following:

4 ........................and you're in the mix with blah blah
5 This is KKJZ....
6 This is KTKE....

This way the only track I ever change is 4 with artist info and the other tracks (5,6) stay relatively static. If I need to add a commercial/PSA/promo for a specific station, I just edit that particular track (5,6) and it gets rendered in seamlessly. In other words, one render contains tracks 4+5 (KTKE), the next render contains 4+6 (KKJZ), etc.

When I'm ready to render the show, I mute all of the station-specific tracks except for the station I'm rendering, open render dialog, rename filename, add to render queue, then move to the next station and unmute that one and mute the previous one, open render dialog, rename the filename, add to render queue, and repeat this for all the stations. Then I run the batch render process.


The problem with this is that it's extremely time-consuming. What I'd really like to do is be able to entirely automate this process so that I can run a script and it will do all the muting/unmuting, open render dialog, rename filenames accordingly, add to render queue, etc. and do it in one fell swoop.

Is there any way to accomplish this? I'd really like to output more versions of the show for other radio stations, but this limitation is keeping me from approaching more stations until I have a usable workflow. If I have 20+ stations, there's no way that the current method is going to manageable on a weekly basis.

Thanks!
Mike
msoultan is offline   Reply With Quote
Old 05-01-2015, 03:37 PM   #2
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Anyone have any ideas? I really need to come up with a solution and I'd prefer to stay with Reaper, if possible. Is there any way to request additional scripting features? If I could script some of the render options, this would definitely be possible. Heck, I'd be willing to pay for the additional features...

Thanks!
Mike
msoultan is offline   Reply With Quote
Old 05-01-2015, 09:17 PM   #3
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

I don't know if you can render via Reaper's scripting API; if so, you could certainly write a script to do what you describe, but if you're not a programmer, it's probably not worth delving into. Someone could possibly do it for you (not me, unfortunately).

Possibly an answer is this: learn how to make custom actions (pull up the action menu with the "?" key).

You could create a custom action that is something like:

-Add project to render queue, using the most recent render settings
-toggle mute for selected tracks
-go to next track
-toggle mute for selected tracks

Then make a second custom action that calls the first custom action however many times (e.g. 20 for 20 stations).

To use it:
- open the render dialog, set the settings how you like, and in the render dialog for the file name use the wildcards "$hour$minute$second", like: show-$hour$minute$second --- this will generate "show-111622.wav", "show-111734.wav", etc. (this is to prevent trying to render over what already was rendered)
- click "Save changes and close" (not "Render" or "Add to render queue")
- select the first station ID track and un-mute it (others are assumed muted)
- run your custom action (the second one)
- render the render queue

The only remaining bummer is that you have to go through the resulting files and rename them. You could automate that with a shell script if you're able.

Someone might pipe up with a more clever method.

Another way might be to create multiple "regions": one that contains the bulk of the show as you have it structured now, but starting at "...and you're in the mix with etc..." That is contained in one region. At the end you have multiple regions, one after the other, that contain the various station IDs. The regions are named for the station ID they contain.

You then render all the regions (a one-step thing in Reaper), and the renders go out to separate files. (If the station IDs never change, you could just render the "show" region and re-use the rendered station IDs, week to week.) Then you could shell script the conjoining of the station IDs with the show. If you have a linux box handy, I bet we could whip something up pretty quick. There are probably GUI tools that could do this? Dunno.
clepsydrae is offline   Reply With Quote
Old 05-06-2015, 04:16 PM   #4
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Quote:
Originally Posted by clepsydrae View Post
I don't know if you can render via Reaper's scripting API; if so, you could certainly write a script to do what you describe, but if you're not a programmer, it's probably not worth delving into. Someone could possibly do it for you (not me, unfortunately).
I looked at the API function list and nothing mentions rendering - am I missing something? I have a friend that programs in C++ so he'd be willing to help out there.

Quote:
Possibly an answer is this: learn how to make custom actions (pull up the action menu with the "?" key).

You could create a custom action that is something like:

-Add project to render queue, using the most recent render settings
-toggle mute for selected tracks
-go to next track
-toggle mute for selected tracks

Then make a second custom action that calls the first custom action however many times (e.g. 20 for 20 stations).

To use it:
- open the render dialog, set the settings how you like, and in the render dialog for the file name use the wildcards "$hour$minute$second", like: show-$hour$minute$second --- this will generate "show-111622.wav", "show-111734.wav", etc. (this is to prevent trying to render over what already was rendered)
- click "Save changes and close" (not "Render" or "Add to render queue")
- select the first station ID track and un-mute it (others are assumed muted)
- run your custom action (the second one)
- render the render queue

The only remaining bummer is that you have to go through the resulting files and rename them. You could automate that with a shell script if you're able.
That's pretty clever, and I could write a vbscript that reads the files generated in the folder and renames them accordingly. That wouldn't be the worst thing, although it would be handier if I could script the filename - I think that's the part that's killing me right now. I guess I'll post a feature suggestion to see if that's something that might be possible.


Quote:
Another way might be to create multiple "regions": one that contains the bulk of the show as you have it structured now, but starting at "...and you're in the mix with etc..." That is contained in one region. At the end you have multiple regions, one after the other, that contain the various station IDs. The regions are named for the station ID they contain.

You then render all the regions (a one-step thing in Reaper), and the renders go out to separate files. (If the station IDs never change, you could just render the "show" region and re-use the rendered station IDs, week to week.) Then you could shell script the conjoining of the station IDs with the show. If you have a linux box handy, I bet we could whip something up pretty quick. There are probably GUI tools that could do this? Dunno.
I think your first idea sounds a bit easier
msoultan is offline   Reply With Quote
Old 05-10-2015, 04:45 PM   #5
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

Quote:
Originally Posted by msoultan View Post
I looked at the API function list and nothing mentions rendering - am I missing something?
Your guess is as good as mine. But yeah, i didn't see anything there either. I guess rendering hooks don't exist for the API?

If you have a programmer friend, you could go a different route: learn what the difference in the RPP files is when you have a given station track unmuted vs. the next track unmuted vs. etc... it's probably just a line or two? (RPP files are plain text, note.)

Then have a master project that you work with. When you want to do a render, save the project file. Then use a vbscript or whatever to make a bunch of copies of the RPP file, one for each station, with the appropriate changes made to unmute each track in turn. Then the same script calls reaper to do a render via command line:

C:\path\to\reaper.exe -renderproject station_KABC.RPP

...i presume that before running it you'd set up the render options and save them without rendering. Perhaps you'd have to render to the same file name each time, and have the script change the name of the file from "output.wav" or whatever to "station_KABC.wav" before it called reaper.exe the next time.

Just some brainstorming.
clepsydrae is offline   Reply With Quote
Old 05-12-2015, 04:58 PM   #6
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Quote:
If you have a programmer friend, you could go a different route: learn what the difference in the RPP files is when you have a given station track unmuted vs. the next track unmuted vs. etc... it's probably just a line or two? (RPP files are plain text, note.)
You know, this might be the easiest way. I'm able to dynamically update the path/filename to where I want the rendered file to go and it's easy enough to figure out what parameters to change in the file by changing settings and comparing the differences by using WinMerge. I can pretty easily parse the file with vbscript to update the MUTESOLO parameter (among others) and update it and render the file.

Quote:
C:\path\to\reaper.exe -renderproject station_KABC.RPP
Where do you find info on command-line parameters?
msoultan is offline   Reply With Quote
Old 05-12-2015, 05:18 PM   #7
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

Quote:
Originally Posted by msoultan View Post
Where do you find info on command-line parameters?
The only place i've found is from running the command itself:

reaper.exe -help

(-help or any other unrecognized option, i take it)

It's not very informative, though... if you find any documentation let me know.
clepsydrae is offline   Reply With Quote
Old 05-12-2015, 05:23 PM   #8
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Yeah, I just did a reaper /h and got the same thing. I was hoping there was more documentation on this stuff, but I guess not.

Regardless, this method does essentially give me lots of access into the reaper file and conceivably I should be able to accomplish what I'm trying to do. I'll play with it and see what I can come up with.

Thanks!!
Mike
msoultan is offline   Reply With Quote
Old 05-13-2015, 04:43 PM   #9
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Btw, any idea what the -batchconvert command-line option does? It takes a text file so I was wondering if that's the same thing as the render queue or something different. Otherwise I can easily generate a batch file that contains the following:

reaper -renderproject file1.rpp
reaper -renderproject file2.rpp
reaper -renderproject file3.rpp
...

So far I've created a script that outputs three different RPPs with the mute status updated for each station. Now I just need to update the render location/filename and build the render batch file. Then I should be good to go

Thanks!
Mike
msoultan is offline   Reply With Quote
Old 05-13-2015, 06:00 PM   #10
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

Quote:
Originally Posted by msoultan View Post
Btw, any idea what the -batchconvert command-line option does? It takes a text file so I was wondering if that's the same thing as the render queue or something different.
I think batchconvert just links to the "batch converter" (see File -> Batch file/item converter), not a rendering process. I'm not sure how it uses the text file; \n-separated list of filenames to render with last-used batch converter settings? I can find zero information about it on the 'net.

Quote:
So far I've created a script that outputs three different RPPs with the mute status updated for each station. Now I just need to update the render location/filename and build the render batch file. Then I should be good to go
Awesome; sounds close. You should post your final script here in case others are interested.
clepsydrae is offline   Reply With Quote
Old 05-14-2015, 11:19 AM   #11
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Ok, I'm running into problems - whenever I run the following command:

Quote:
"c:\Program Files\REAPER (x64)\reaper.exe" -renderproject "show.RPP"
I get the following error:

Quote:
There was an error opening the project: show.RPP
I can open the file just fine, go to the render dialog, and render the file - it just doesn't work from the command-line. Any ideas what's up?

Thanks!
Mike

Last edited by msoultan; 05-14-2015 at 11:27 AM.
msoultan is offline   Reply With Quote
Old 05-14-2015, 11:28 AM   #12
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

Have you tried giving a more proper path?

e.g.

"c:\Program Files\REAPER (x64)\reaper.exe" -renderproject "c:\full\path\to\show.RPP"
clepsydrae is offline   Reply With Quote
Old 05-14-2015, 11:29 AM   #13
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Quote:
Originally Posted by clepsydrae View Post
Have you tried giving a more proper path?

e.g.

"c:\Program Files\REAPER (x64)\reaper.exe" -renderproject "c:\full\path\to\show.RPP"
Ha! I *just* tried that right as I heard my phone buzz that I got an email and yup, that worked

Continuing on with the script....
msoultan is offline   Reply With Quote
Old 05-14-2015, 11:43 AM   #14
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Ok.. I think I got it working - I'm gonna test it out a bit and then clean up the script. Once I'm comfortable that it's working ok (and the script isn't a complete mess), I'll post it up!
msoultan is offline   Reply With Quote
Old 05-14-2015, 11:54 AM   #15
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

Good luck!
clepsydrae is offline   Reply With Quote
Old 05-15-2015, 11:11 AM   #16
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

So I've got a working version of my script. I'm sure I'm gonna tweak and improve it over the coming months, but at least this is something for others to work with if they find it helpful:

Code:
'****************************************************************************************
'****************************************************************************************
'**   Reaper Radio Show Rendering Utility (RenderShow.vbs)
'**
'**   Copyright (C) 2015 - Mike Soultanian - mike@soultanian.com
'**
'**   This program is free software; you can redistribute it and/or
'**   modify it under the terms of the GNU General Public License
'**   as published by the Free Software Foundation; either version 2
'**   of the License, or (at your option) any later version.
'**
'**   This program is distributed in the hope that it will be useful,
'**   but WITHOUT ANY WARRANTY; without even the implied warranty of
'**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'**   GNU General Public License for more details.
'**
'**   You should have received a copy of the GNU General Public License
'**   along with this program; if not, write to the Free Software
'**   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
'**
'**   This header must appear on all derivatives of this code.
'****************************************************************************************
'****************************************************************************************

'v1.0 - Initial release

'This script is used to render the Soul-Titanium radio show for multiple radio stations.
'The Reaper file is structured in such a way that there are station-specific tracks that
'contain station-specific audio like commercials and station IDs.  Usually you'd have to
'manually un-mute each of these tracks and then render that station's show, but this script
'automatically does that for you.


'these values need to be modified to match the Reaper audio configuration
Const TrackNames = "KTKE,KKJZ,Web"
Const Format = 1 '1=MP3, 2=WAV
Const PathToReaper = "c:\Program Files\REAPER (x64)\reaper.exe"
Const RenderPath = "C:\Users\Mike\Documents\REAPER Media\Soul-Titanium\"



'-Do not change anything below here---------------------------------------------------------------------'
Const RenderFilePrefix = "  RENDER_FILE "
Const RenderCfgMP3 = "    bDNwbQABAAABAAAA//////////8EAAAAAAEAAAAAAAA="
Const RenderCfgWAV = "    ZXZhdxAA"
Const DontWaitUntilFinished = false, ShowWindow = 1, DontShowWindow = 0, WaitUntilFinished = true
Const ForReading = 1, ForWriting = 2, ForAppending = 8 
Const UnMuted = "    MUTESOLO 0 0 0", 	Muted = "    MUTESOLO 1 0 0"
Const ReaperFile = "show.RPP"

Set objFSO = CreateObject("Scripting.FileSystemObject")
set objShell = WScript.CreateObject("WScript.Shell")

If Format = 1 Then
	strRenderExt = ".mp3"
	strRenderCfg = RenderCfgMP3
ElseIf Format = 2 Then
	strRenderExt = ".wav"
	strRenderCfg = RenderCfgWAV

Else
	Wscript.Echo "Incorrect extension specified.  Quitting"
End If


'read show.RPP file into array
Set objFile = objFSO.OpenTextFile(ReaperFile, ForReading)
strTextFile = objFile.ReadAll
arrTextFile = Split(strTextFile, VbNewLine)
objFile.Close

'convert the list of track names to process to an array so it's easier to loop through
strTrackNames = LCase(TrackNames)
arrStationTracks = Split(strTrackNames, ",")

'create an array with the same dimensions as the track names array to store the line locations of the MUTUSOLO parameter
IntSize =  UBound(arrStationTracks)
ReDim Preserve arrMuteSoloLoc(IntSize)

'pull the guest DJ name and show number from the path
strScriptDir = objFSO.GetParentFolderName(wscript.ScriptFullName) & "\"
strParentFolder = objFSO.GetParentFolderName(strScriptDir)
intBackSlashLoc = InStrRev(LCase(strParentFolder), "\")
strShowNameNum = Right(strParentFolder, Len(strParentFolder) - intBackSlashLoc)

'get show number
intShowNumLoc = InStr(strShowNameNum, "show ") + 5
intShowNumLen = InStr(intShowNumLoc, LCase(strShowNameNum), " ") - intShowNumLoc
strShowNumber = Trim(mid(strShowNameNum, intShowNumLoc, intShowNumLen))

'get guest dj name
intDashLoc = InStr(strShowNameNum, "-")
strDJName = ProperCase(Trim(Right(strShowNameNum, Len(strShowNameNum) - intDashLoc)))


'loop through all the tracks to be processed
For intStation = 0 to UBound(arrStationTracks)
	'loop through the entire show.RPP file stored in memory and mute all the tracks to be processed
	blnLookingForMuteSolo = FALSE
	For intLineNum = LBound(arrTextFile) to UBound(arrTextFile)
		'track header found - see if it matches the current station track we're processing.  If not, move on
		If InStr(LCase(arrTextFile(intLineNum)), "<track {") and blnLookingForMuteSolo Then
			wscript.echo "MUTESOLO parameter missing because I'm at the next track marker without finding a MUTESOLO statement.  Quitting."
			wscript.quit
		End If

		If InStr(LCase(arrTextFile(intLineNum)), "<track {") Then
			If InStr(LCase(arrTextFile(intLineNum+1)), arrStationTracks(intStation)) Then
				'current block matches the current track that we're searching for so let's start looking for the MUTESOLO parameter
				blnLookingForMuteSolo = TRUE
			End If
		End If

		If InStr(LCase(arrTextFile(intLineNum)), "mutesolo") and blnLookingForMuteSolo Then
			'we've confirmed that we've found the MUTESOLO 
			arrTextFile(intLineNum) = Muted
			arrMuteSoloLoc(intStation)=intLineNum
			blnLookingForMuteSolo = FALSE
		End If
	Next
Next
objFile.Close


'loop through all of the tracks and unmute each one and write out a temporary RPP file for rendering
For s = 0 to UBound(arrStationTracks)
	Set objFile = objFSO.OpenTextFile("TEMP-" & UCase(arrStationTracks(s)) & "-" & ReaperFile, ForWriting, true)
	
	'loop through the text file in memory, update the render path and appropriate mute setting, and save to a temporary render file
	intRenderCfg = -1
	For intLineNum = LBound(arrTextFile) to UBound(arrTextFile)
		If InStr(LCase(arrTextFile(intLineNum)), "render_file") Then
			objFile.Write(RenderFilePrefix & """" & RenderPath & "show-" & strShowNumber & "-" & arrStationTracks(s) & strRenderExt & """" & VbNewLine)
		ElseIf InStr(LCase(arrTextFile(intLineNum)), "<render_cfg") Then
			'found the render_cfg tag, because the rest of the cfg is on the following line, store the next line number
			intRenderCfg = intLineNum + 1
			objFile.Write(arrTextFile(intLineNum) & VbNewLine)
		ElseIf intRenderCfg = intLineNum Then
			objFile.Write(strRenderCfg & VbNewLine)
		ElseIf intLineNum = arrMuteSoloLoc(s) Then
			objFile.Write(UnMuted & VbNewLine)
		Else
			objFile.Write(arrTextFile(intLineNum) & VbNewLine)
		End If
	Next
	objFile.Close
	
	'run reaper and render show
	objShell.Run """" & PathToReaper & """ -renderproject """ & strScriptDir & "TEMP-" & UCase(arrStationTracks(s)) & "-" & ReaperFile & """", DontShowWindow, WaitUntilFinished
	objFSO.DeleteFile strScriptDir & "TEMP-" & UCase(arrStationTracks(s)) & "-" & ReaperFile
	If InStr(strRenderExt, "mp3") Then
		'apply ID3 tag to newly created MP3
		objShell.Run """" & strScriptDir & "id3.exe"" -12 -t ""Soul-Titanium Radio Show " & strShowNumber & " - " & strDJName & """ -a ""Mike Soultanian"" -g ""House"" """ & RenderPath & "show-" & strShowNumber & "-" & arrStationTracks(s) & strRenderExt & """", DontShowWindow, WaitUntilFinished
	End If
Next



'=-=-=-=-=-=-=
'Functions
'=-=-=-=-=-=-=

Function ProperCase(sText)
'*** Converts text to proper case e.g.  ***'
'*** surname = Surname                  ***'
'*** o'connor = O'Connor                ***'
 
    Dim a, iLen, bSpace, tmpX, tmpFull
 
    iLen = Len(sText)
    For a = 1 To iLen
    If a <> 1 Then 'just to make sure 1st character is upper and the rest lower'
        If bSpace = True Then
            tmpX = UCase(mid(sText,a,1))
            bSpace = False
        Else
        tmpX=LCase(mid(sText,a,1))
            If tmpX = " " Or tmpX = "'" Then bSpace = True
        End if
    Else
        tmpX = UCase(mid(sText,a,1))
    End if
    tmpFull = tmpFull & tmpX
    Next
    ProperCase = tmpFull
End Function

Last edited by msoultan; 05-15-2015 at 02:46 PM.
msoultan is offline   Reply With Quote
Old 05-15-2015, 12:16 PM   #17
clepsydrae
Human being with feelings
 
clepsydrae's Avatar
 
Join Date: Nov 2011
Posts: 3,409
Default

Congrats! Long way to go, but way to stick it out.

Maybe some day Reaper can have "scripting" in the traditional sense, like:

- open project
- mute track 1
- unmute track 2
- adjust levels on track named 'bass' to X
- disable plugin named 'blah' on track named 'blah'
- render project with the following settings to file X: format=blah, name=blah

Seems like a lot of the infrastructure is already there...
clepsydrae is offline   Reply With Quote
Old 05-15-2015, 12:30 PM   #18
msoultan
Human being with feelings
 
Join Date: Jul 2013
Posts: 70
Default

Yeah, kinda surprising that you can't script this already, but I'm happy I was happy to be able to pull it off! Thanks for your help
msoultan is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:13 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.