Script to remux mkv to mp4 using ffmpeg issues

Hi

I need a script that searches a folder for mkv files and remux them to mp4 container using ffmpeg.

I’ve got this old script, I’ve been using for years. But it uses Handbrake and is very slow, and I still loose some of the quality.

Here is the script I’ve been using on my old mac mini. But I can’t “see” what I need to do to get it to work as needed.

–on adding folder items to this_folder after receiving these_items
with timeout of (720 * 60) seconds
tell application “Finder”
–Get all AVI and MKV files that have no label color yet, meaning it hasn’t been processed
set allFiles to every file of entire contents of (folder “Multimedia:TV”) whose ((name extension is “avi” or name extension is “mkv”) and label index is 0)

	--Repeat for all files in above folder
	repeat with i from 1 to number of items in allFiles
		set currentFile to (item i of allFiles)
		
		try
			--Set to gray label to indicate processing
			set label index of currentFile to 7
			
			--Assemble original and new file paths
			set origFilepath to quoted form of POSIX path of (currentFile as text)
			set newFilepath to (characters 1 thru -5 of origFilepath as string) & "mp4'"
			
			--Start the conversion
			set shellCommand to "nice /Applications/HandBrakeCLI -i " & origFilepath & " -o " & newFilepath & " -e x264  -q 18.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 --decomb --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.1"
			do shell script shellCommand
			
			--Set the label to green in case file deletion fails
			set label index of currentFile to 6
			
			--Remove the old file
			set shellCommand to "rm -f " & origFilepath
			do shell script shellCommand
		on error errmsg
			--Set the label to red to indicate failure
			set label index of currentFile to 6
		end try
	end repeat
end tell

end timeout
–end adding folder items to

Hi.

Besides the time taken to do the conversions (about which I don’t know enough to be able to offer any advice), a possible major bottleneck in the script is the Finder’s ‘entire contents’ command, which can take a very long time if there are a large number of items and is here picking out ‘files’ and applying a ‘whose’ filter with three conditions.

One alternative is to use a ‘find’ shell script to find AVI and MKV files, although the Finder would still have to check the label indices:

-- Original Finder reference used to identify the root folder as it's not clear if it's in a volume called "Multimedia" or in a folder of that name on the user's desktop.
tell application "Finder" to set rootFolderAlias to folder "Multimedia:TV" as alias

--Get POSIX paths to all AVI and MKV files. Label indices will be checked below.		
set allPaths to paragraphs of (do shell script "find -f " & quoted form of POSIX path of rootFolderAlias & " \\( -name '*.avi' -or -name '*.AVI' -or -name '*.mkv' -or -name '*.MKV' \\)")

-- Repeat for all paths obtained.
repeat with thisPath in allPaths
	set currentFile to (POSIX file thisPath) as alias
	
	-- Get this file's label index. If it's 0, the file hasn't been processed yet. 
	tell application "Finder" to set currentLabelIndex to label index of currentFile
	if (currentLabelIndex is 0) then
		try
			--Set to gray label to indicate processing
			tell application "Finder" to set label index of currentFile to 7
			
			--Assemble original and new file paths
			set origFilePath to quoted form of thisPath
			set newFilepath to (text 1 thru -5 of origFilePath) & "mp4'"
			
			--Start the conversion
			set shellCommand to "nice /Applications/HandBrakeCLI -i " & origFilePath & " -o " & newFilepath & " -e x264  -q 18.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 --decomb --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.1"
			do shell script shellCommand
			
			--Set the label to green in case file deletion fails
			tell application "Finder" to set label index of currentFile to 6
			
			--Remove the old file
			set shellCommand to "rm -f " & origFilePath
			do shell script shellCommand
		on error errmsg
			--Set the label to green to indicate failure
			tell application "Finder" to set label index of currentFile to 6
		end try
	end if
end repeat

Another way involves the use of ASObjC, which can also be used instead of the Finder to check and set the labels:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

-- Original Finder reference used to identify the root folder as it's not clear if it's in a volume called "Multimedia" or in a folder of that name on the user's desktop.
tell application "Finder" to set rootFolderAlias to folder "Multimedia:TV" as alias

set |⌘| to current application
set rootFolderURL to |⌘|'s class "NSURL"'s fileURLWithPath:(POSIX path of rootFolderAlias)
set fileManager to |⌘|'s class "NSFileManager"'s defaultManager()
set labelNumberKey to |⌘|'s NSURLLabelNumberKey

-- Get URLs to the folder's entire visible contents along with the relevant label numbers.
set allURLs to (fileManager's enumeratorAtURL:(rootFolderURL) includingPropertiesForKeys:({labelNumberKey}) options:(|⌘|'s NSDirectoryEnumerationSkipsHiddenFiles) errorHandler:(missing value))'s allObjects()
-- Filter the items to just those whose name extensions are "avi" or "mkv".
set AVIOrMKVURLPredicate to |⌘|'s class "NSPredicate"'s predicateWithFormat:("pathExtension.lowercaseString IN {'avi','mkv'}")
set AVIOrMKVURLs to allURLs's filteredArrayUsingPredicate:(AVIOrMKVURLPredicate)

-- Repeat for all the AVI and MKV URLs obtained.
repeat with origURL in AVIOrMKVURLs
	-- Get this URL's label number. If it's 0, the file hasn't been processed yet.
	set {success, labelNumber} to (origURL's getResourceValue:(reference) forKey:(labelNumberKey) |error|:(missing value))
	if ((labelNumber is not missing value) and (labelNumber as integer is 0)) then
		try
			--Set to gray label to indicate processing
			-- Apart from 0, label numbers are 8 minus the equivalent Finder label indices.
			tell origURL to setResourceValue:(8 - 7) forKey:(labelNumberKey) |error|:(missing value)
			
			--Assemble original and new file paths
			set origFilePath to origURL's |path|()
			set newFilePath to (origFilePath's stringByDeletingPathExtension()'s stringByAppendingPathExtension:("mp4"))
			
			--Start the conversion.
			set shellCommand to "nice /Applications/HandBrakeCLI -i " & quoted form of (origFilePath as text) & " -o " & quoted form of (newFilePath as text) & " -e x264  -q 18.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 --decomb --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.1"
			do shell script shellCommand
			
			--Set the label to green in case file deletion fails
			tell origURL to setResourceValue:(8 - 6) forKey:(labelNumberKey) |error|:(missing value)
			
			--Remove the old file
			tell fileManager to removeItemAtURL:(origURL) |error|:(missing value)
		on error errmsg
			--Set the label to green to indicate failure
			tell origURL to setResourceValue:(8 - 6) forKey:(labelNumberKey) |error|:(missing value)
		end try
	end if
end repeat

As in the original script, the ‘try’ block isn’t entirely foolproof in either of these alternatives, as one of the possible reasons for not being able to delete a file is that it’s locked — in which case you won’t be able to set its label index either. The ASObjC commands don’t generate AppleScript errors if they’re unsuccessful, but errors can be generated based on their results if desired. It didn’t seem worth the bother here.