I modified the script in this post at 8:45am pacific time on March 17, 2017
I changed the way the video time length was converted from seconds to a HH:MM:SS format. It now uses NSDateComponentsFormatter to calculate this value.
I modified the script in this post at 12:04 pacific time on March 16, 2017
Shane pointed out there was useless code my script. So I removed the useless code involving the notification stuff. So this makes my second final change. I do remember Shane telling me not long ago. “Never say never.” I guess he he was right about that part too 
I modified the script in this post at 7:28 pacific time on March 15, 2017
Richard Parker, a friend of mine, told me how to the fix the script so it would work with backslashes (\) in the file name. I added code toward the top of the “repeat with TheFile in FileList” repeat loop. So the script in this post will now work when a backslashes (\) are in the file name. The comments in the script point out where the change were made and what was done to fix it.
The changes consisted of adding the following 4 lines.
if ((offset of "\\" in (FileName as text)) ≠ 0) then
-- There is at least 1 backslash in the filename
set FileName to SeachAndReplace("\\", "\\\\", (FileName as text)) -- Replace every backslash in file name with 4 backslashes
end if
I also added 4 line of comments above that to explain why this was needed and why it works.
For anyone interested,
Shane,
I changed the script so Finder tell blocks were only used where needed instead of me being lazy and putting everything in one big Finder tell block. That got rid of all the problems except when there is a \ character in the file name. This causes the search to fail to find itself in it’s own enclosing folder. I have no idea how to get around this. I spent hours and didn’t get anywhere. But the rest of this works.
I added a bunch of comments to this code to make it easier to follow. But this is it for me changing it. It will work as long as there is no \ character in the file name.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
-- This script sends a sportligh search request to a single file at a time and sets the searchbounds to be the enclosing folder the file is in.
-- So it is a 1 file search. But after doing this 1 file search all the spotligh atributes for the file can be accessed.
property AceptableFileExtensions : {"mp4"} -- Add more video file extentions as I come across them
property WindowLevelOffest : 0
on MakeMiniBBEditWin(WindowName, DocText)
-- Used a script object here in case I ever want to pass something back from this handler other then it succed or failed
script ReturnObj
property Successful : false
end script
try
tell application "BBEdit"
make new document with properties {name:WindowName, text:DocText, bounds:{50 + (WindowLevelOffest * 40), 60 + (WindowLevelOffest * 40), 700 + (WindowLevelOffest * 40), 100 + (WindowLevelOffest * 40)}} -- {left, top, right, bottom}
end tell
set (Successful of ReturnObj) to true
return ReturnObj
on error errMsg number errNum
display dialog "Error " & (errNum as string) & " occured while creating the BBEdit document." & return & return & errMsg ¬
with title "Error"
set (Successful of ReturnObj) to false
return ReturnObj
end try
end MakeMiniBBEditWin
-------------------------------------------------------------
on CreateResults(VideoName, PixelHeight, PixelWidth, FileSize, ItemKind, VideoLength, AudioBitRate, VideoBitRate)
-- Creates the text to be displayed for the user. Most of this handler creates text to the MakeMiniBBEditWin handler which will display the output in a window
-- Used a script object here in case I ever want to pass something back from this handler other then it succed or failed
script ReturnObj
property Successful : false
end script
set TheText to ""
try
-- This creates a special output for the file size. Out put the number of kb, mb, tb, ... then displays the exact number of bytes to the right of the first number
if (FileSize ≠ missing value) then
-- Calculate the file size
set theFormatter to current application's NSByteCountFormatter's alloc()'s init()
theFormatter's setCountStyle:(current application's NSByteCountFormatterCountStyleDecimal)
theFormatter's setIncludesActualByteCount:true
set ConvertedFileSize to theFormatter's stringFromByteCount:FileSize
else
set ConvertedFileSize to missing value
end if
if (VideoName ≠ missing value) then
set TheText to TheText & "Video name: " & VideoName & return & return
else
set TheText to TheText & "Video name: Could not find the video file name" & return & return
set VideoName to "Untitled"
end if
if ((PixelHeight ≠ missing value) and (PixelWidth ≠ missing value)) then
set TheText to TheText & "Video size: " & PixelHeight & " X " & PixelWidth & return & return
else if ((PixelHeight = missing value) and (PixelWidth = missing value)) then
set TheText to TheText & "Video size: " & "\"Pixel height\" and \"pixel width\" not found." & return & return
else if (PixelHeight = missing value) then
set TheText to TheText & "Video size: " & "\"Pixel height not found.\"" & " X " & PixelWidth & return & return
else if (PixelWidth = missing value) then
set TheText to TheText & "Video size: " & PixelHeight & " X " & "\"Pixel width not found.\"" & return & return
end if
if (ConvertedFileSize ≠ missing value) then
set TheText to TheText & "File size: " & ConvertedFileSize & return & return
else
set TheText to TheText & "File size: " & "missing value" & return & return
end if
if (VideoLength ≠ missing value) then
set TheText to TheText & "Video length: " & VideoLength & return & return
else
set TheText to TheText & "Video length: " & "missing value" & return & return
end if
if (ItemKind ≠ missing value) then
set TheText to TheText & "Item Kind: " & ItemKind & return & return
else
set TheText to TheText & "Item Kind: " & "missing value" & return & return
end if
if (VideoBitRate ≠ missing value) then
set TheText to TheText & "Video Bit Rate: " & VideoBitRate & return & return
else
set TheText to TheText & "Video Bit Rate: " & "missing value" & return & return
end if
if (AudioBitRate ≠ missing value) then
set TheText to TheText & "Audio Bit Rate: " & AudioBitRate
else
set TheText to TheText & "Audio Bit Rate: " & "missing value" & return & return
end if
set TheResult to MakeMiniBBEditWin(VideoName, TheText)
if (not (Successful of TheResult)) then
set (Successful of ReturnObj) to false
return ReturnObj
end if
set (Successful of ReturnObj) to true
return ReturnObj
on error errMsg number errNum
display dialog "Error " & (errNum as string) & " occured while creating the results to display." & return & return & errMsg buttons {"OK"} default button ¬
"OK" with title "Error"
set (Successful of ReturnObj) to false
return ReturnObj
end try
end CreateResults
-------------------------------------------------------------
on Make2Digits(TheNumber)
-- Make sure 2 digits number string are always retuned even when given single digit numbers
if (TheNumber < 10) then
return "0" & (TheNumber as text)
else
return (TheNumber as text)
end if
end Make2Digits
-------------------------------------------------------------
on SeachAndReplace(SearchStr, ReplaceStr, TheStr)
set OldASDelimiters to text item delimiters of AppleScript
set text item delimiters of AppleScript to {SearchStr as string}
set TheList to text items of TheStr
set text item delimiters of AppleScript to {ReplaceStr as string}
set TheNewStr to TheList as string
set text item delimiters of AppleScript to OldASDelimiters
return TheNewStr
end SeachAndReplace
-------------------------------------------------------------
-- This is used to offset the window horizonatally and vertically when multiple windows are produced so the windows don't all end up completely covering the window below it.
set WindowLevelOffest to 0
tell application "Finder"
-- This creates a list of the files selected in Finder
set FileList to selection
-- Checks that something is selected in Finder
if (FileList = {}) then
display dialog "!There are no items selected in the Finder. Please select some video files." buttons {"OK"} default button "OK" with title "Error"
return false
end if
end tell
-- This assumes the AceptableFileExtensions list is complete and if a file extension does not appear in the list it is not a video file.
-- In practice if I run across a video not in the list I just add it to the AceptableFileExtensions list and eventually it will get fairly complete
if (FileList ≠ {}) then
tell application "Finder"
repeat with TheFile in FileList
if (AceptableFileExtensions does not contain ((name extension of TheFile) as text)) then
display dialog "1 or more itmes selected in the Finder is not a video file." buttons {"OK"} default button "OK" with title "Error"
return false
end if
end repeat
end tell
-- This loop goes through all the files selected in Finder, determines the infor to display for each file and display that data in a data window
repeat with TheFile in FileList
-- Get the file path as a NSString
tell application "Finder" to set TheFilePath to (current application's NSString's stringWithString:(POSIX path of (TheFile as text)))
set FileName to TheFilePath's lastPathComponent() -- Uses NSString's lastPathComponent function
-- NOTE: If there is a backslash in FileName then both AppleScript and the predicate will consider 2 backslashes in a string to represent
-- a single backslash when the string is evaluated. So the string 123\45 would be represented by 123\\\\45. The predicate would
-- see 123\\\\45 as representing 123\\45 and later on apple would see 123\\45 as representing 123\\45.
-- So if an backslashes are detected in FileName is changed to 4 backslashes.
if ((offset of "\\" in (FileName as text)) ≠ 0) then
-- There is at least 1 backslash in the filename
set FileName to SeachAndReplace("\\", "\\\\", (FileName as text)) -- Replace every backslash in file name with 4 backslashes
end if
set EnclosingFolderPath to TheFilePath's stringByDeletingLastPathComponent() -- Uses NSString's stringByDeletingLastPathComponent function
--This creates a SearchPredicate to add to the SearchQuery
set SearchPredicate to current application's NSPredicate's predicateWithFormat_("kMDItemFSName == %@", FileName)
-- Creates a blank SearchQuery
set SearchQuery to current application's NSMetadataQuery's alloc()'s init()
(SearchQuery's setPredicate:SearchPredicate) --Adds the Predicate to the SearchQuery
(SearchQuery's setSearchScopes:{EnclosingFolderPath}) -- Tells SearchQuery where to search
SearchQuery's startQuery() -- Starts the search process
-- Once the search has stopped gathering information "isGathering" turns to false and control drops out of the loop
-- Then the script starts process line in the script after the loop
repeat while SearchQuery's isGathering() as boolean
delay 0.01
end repeat
-- This tell the query the search is done
SearchQuery's stopQuery()
-- This is a check in case the file being access has none attributes being looked for. If this is the case then script returns a default response and quits.
if ((SearchQuery's results()) as list = {}) then
-- The results list is empty meaning nothing was found
set ErrorText to "Unable to find any metadata information for the file."
my MakeMiniBBEditWin(FileName as text, ErrorText)
return false
end if
-- The output for the search is returned in a array. The results that contain the info being looked for are in the 0th position in the array
set MetadataItem to (SearchQuery's resultAtIndex:0)
-- This part tell the MetadataItem what thing to create a dictionary for.
set TheDictionary to (MetadataItem's valuesForAttributes:{current application's kMDItemPixelHeight, current application's kMDItemPixelWidth, current application's kMDItemFSSize, ¬
current application's kMDItemKind, current application's kMDItemAudioBitRate, current application's kMDItemVideoBitRate, current application's kMDItemFSName, ¬
current application's kMDItemDurationSeconds})
-- This part reads those values from the dictionary
set PixelHeight to (TheDictionary's objectForKey:"kMDItemPixelHeight") as text
set PixelWidth to (TheDictionary's objectForKey:"kMDItemPixelWidth") as text
set FileSize to (TheDictionary's objectForKey:"kMDItemFSSize")
set ItemKind to (TheDictionary's objectForKey:"kMDItemKind") as text
set AudioBitRate to (TheDictionary's objectForKey:"kMDItemAudioBitRate") as text
set VideoBitRate to (TheDictionary's objectForKey:"kMDItemVideoBitRate") as text
set VideoName to (TheDictionary's objectForKey:"kMDItemFSName") as text
set LengthInSeconds to (TheDictionary's objectForKey:"kMDItemDurationSeconds") as real
-- This part takes the number of seconds in the viedo and converts it to a string of the for HH:MM:SS
if ((LengthInSeconds ≠ missing value) and (class of LengthInSeconds = real)) then
-- LengthInSeconds is not equal to missing value and is a number
set TheHours to LengthInSeconds div hours
set RemainingSeconds to LengthInSeconds - (TheHours * hours)
set TheMinutes to (RemainingSeconds div minutes)
set TheSeconds to (RemainingSeconds mod minutes) div 1 -- The div 1 makes it an integer
set VideoLength to (TheHours as text) & ":" & my Make2Digits(TheMinutes) & ":" & my Make2Digits(TheSeconds)
else
set VideoLength to missing value
end if
-- Call the handler that creates the text to be displayed for the user and calls a handler to display that text
set TheResult to my CreateResults(VideoName, PixelHeight, PixelWidth, FileSize, ItemKind, VideoLength, AudioBitRate, VideoBitRate)
if (not (Successful of TheResult)) then
return false
end if
set WindowLevelOffest to WindowLevelOffest + 1
end repeat
end if