File metadata information

All the alternatives here rely on Spotlight, which won’t index your NAS disks. In fact, I think you will find that Get Info also fails to get the duration of files stored on your NAS disks, for the same reason.

You can, however, get it using AVFoundation. This script requires 10.11 or later:

use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use framework "AVFoundation"
use scripting additions

-- get files
set theFolder to choose folder
set theURL to current application's |NSURL|'s fileURLWithPath:(POSIX path of theFolder)
set fileManager to current application's NSFileManager's defaultManager()
set {theFiles, theError} to fileManager's contentsOfDirectoryAtURL:theURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(reference)
-- eliminate non-video files
set thePred to current application's NSPredicate's predicateWithFormat:"pathExtension IN %@" argumentArray:{{"mp4", "mov", "webm"}}
set vidFiles to theFiles's filteredArrayUsingPredicate:thePred

-- set up results array, formatter for duration
set theResults to current application's NSMutableArray's array()
set theFormatter to current application's NSDateComponentsFormatter's new()

-- lop through
repeat with aFile in vidFiles
	-- get localized name
	set {theResult, theName, theError} to (aFile's getResourceValue:(reference) forKey:(current application's NSURLLocalizedNameKey) |error|:(reference))
	-- create an AVAsset so you can get duration
	set theAsset to (current application's AVURLAsset's assetWithURL:aFile)
	set durationInfo to theAsset's duration() -- returns record like: {value:2911360, timescale:1000, flags:1, epoch:0}
	if durationInfo is missing value then
		set theTime to "unknown"
	else
		-- calculate duration in seconds and format as string
		set theDuration to (value of durationInfo) / (timescale of durationInfo)
		set theDuration to (theFormatter's stringFromTimeInterval:theDuration)
	end if
	(theResults's addObject:(current application's NSString's stringWithFormat_("%@	%@", theName's stringByDeletingPathExtension(), theDuration)))
end repeat
return (theResults's componentsJoinedByString:linefeed) as text

Exactly, “Get Info” fails to get the duration of files stored on my NAS disks.

I ran the script created by Shane and it now work on my NAS.

I’ll keep working on the script because this is only the beginning.

Many thanks everybody, this was impossible for me to write something like this. I do have a real lack of knowledge when comes to write such AppleScript programs.

You guys are great!

MANY THANKS!

Daniel

Hey all I am a total novice at this . So sorry if I don’t speak the language you would understand

I only recently found how apple scripts can make my life so much easier

Shane thank you so much for this . It works great

Thank you for your time , It is greatly appreciated

I was wandering after the last line: return (theResults’s componentsJoinedByString:linefeed) as text

What would I need to add that the script opens Text edit app and copies the the result that appeared as text of the result box of script editor

Here is a link to the image to explain what information I would like to be able to save in a text document

https://imgur.com/jfX5Zez

If its possible can the text file be saved in the same location when the script prompted in the beginning where I selected the folder that contained the media

Hopefully I have explained what I am looking to do

Again thank you so much

Here is how to write to text file. But with avi and mkv movies the Shane’s script gives durations=0. I don’t know why. Well, to write durations to text file replace this:

return (theResults's componentsJoinedByString:linefeed) as text

with this:


set aText to (theResults's componentsJoinedByString:linefeed) as text

set filepath to (POSIX path of theFolder) & "myMoviesDurations.txt"

set openfile to open for access filepath with write permission
write aText as «class utf8» to openfile
close access openfile

Presumably for the same reason QuickTime can’t play them – they’re not formats supported by AVFoundation. A pity.

KniazidisR Thank you…You are a legend !!

It would of been great if AVFoundation supported more formats

Luckily I need it for .mov and .mp4 files

Again I can’t thank everyone enough that contributed to the forum

Maybe I am pushing my luck here a bit but would it be possible to get the duration with frames also
for eg. 01(hours)04(minutes)23(seconds)04(frames) > 01:04:23:04

also could I set the “myMoviesDurations.txt” to the name of the folder the media is sitting in (POSIX path of theFolder)

OK…:


use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use framework "AVFoundation"
use scripting additions

-- get files
set theFolder to choose folder
set theURL to current application's |NSURL|'s fileURLWithPath:(POSIX path of theFolder)
set fileManager to current application's NSFileManager's defaultManager()
set {theFiles, theError} to fileManager's contentsOfDirectoryAtURL:theURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(reference)
-- eliminate non-video files
set thePred to current application's NSPredicate's predicateWithFormat:"pathExtension IN %@" argumentArray:{{"mp4", "mov", "webm"}}
set vidFiles to theFiles's filteredArrayUsingPredicate:thePred

-- set up results array, formatter for duration
set theResults to current application's NSMutableArray's array()
set theFormatter to current application's NSDateComponentsFormatter's new()

-- lop through
repeat with aFile in vidFiles
	-- get localized name
	set {theResult, theName, theError} to (aFile's getResourceValue:(reference) forKey:(current application's NSURLLocalizedNameKey) |error|:(reference))
	-- create an AVAsset so you can get duration
	set theAsset to (current application's AVURLAsset's assetWithURL:aFile)
	set durationInfo to theAsset's duration() -- returns record like: {value:2911360, timescale:1000, flags:1, epoch:0}
	
	if durationInfo is missing value then
		set theTime to "unknown"
		set framesNumber to "unknown"
	else
		-- calculate duration in seconds and format as string
		set theSeconds to (value of durationInfo) / (timescale of durationInfo)
		set theDuration to (theFormatter's stringFromTimeInterval:theSeconds)
		-- Determine frames number here
		set theTracks to (get theAsset's tracks())
		repeat with i from 1 to count theTracks
			set aTrack to item i of theTracks
			if (aTrack's mediaType()) as string is "vide" then exit repeat
		end repeat
		set videoTrack to aTrack
		set frameRate to videoTrack's nominalFrameRate()
		set framesNumber to (theSeconds * frameRate) as integer
	end if
	
	(theResults's addObject:(current application's NSString's stringWithFormat_("%@	%@:%@", theName's stringByDeletingPathExtension(), theDuration, framesNumber)))
end repeat

set aText to (theResults's componentsJoinedByString:linefeed) as text

tell application "Finder" to set folderName to name of theFolder
set filepath to (POSIX path of theFolder) & folderName & ".txt"
set openfile to open for access filepath with write permission
set eof of openfile to 0
write aText as «class utf8» to openfile
close access openfile

KniazidisR that is awesome . Thank you

I see the script works out the entire frame count of the full duration of the file for eg 6530 which is the correct amount of frames for a 4min21sec05frames file at 25frames per a second

The duration of the file I have for eg. 00(h):04(m):21(sec):05(frames)

The previous script would just give the duration of 4m21sec and discard the 05 frames

How can I get the whole timecode represented with out the script rounding off the frames to the closest second ?

I was thinking if we started with the the full frame count and went from frames > timecode

I found the below script about getting frame count and converting to timecode but I haven’t figured how to apply it to KniazidisR frame count in the last script he wrote

tell application “QuickTime Player”
tell document 1 to set {currentTime, timeScale, theDuration, FrameCount} to {current time, time scale, duration, count (frames of track “Video track”)}
end tell

set FrameRate to (FrameCount * timeScale) / theDuration div 1
tell (currentTime / timeScale) to set {hr, mn, sc} to {it div 3600, it mod 3600 div 60, it mod 3600 mod 60 div 1}
set fr to (currentTime mod timeScale div (timeScale / FrameRate))
set SMPTE to addZero(TimeOffset + hr) & “:” & addZero(mn) & “:” & addZero(sc) & “:” & addZero(fr)
display dialog "TCR " & SMPTE

Could anyone help

What I am asking is there a way from the original script in this forum to have not just the hour:Minutes:seconds displayed but also the frames so the whole timecode of each video
hh:mm:ss:ff

Thank you all for your help

I will continue to try

Hi, byronheath.
If I understood correctly, then you just need to replace this in my script:

set framesNumber to (theSeconds * frameRate) as integer

with this:

set framesNumber to round ((theSeconds * frameRate) - ((theSeconds * frameRate) as integer))

Thank you so much for helping me you are a legend

Sorry I am not explaining it well

I have attached a video link so you can see it in visual form

I have burnt in timecode so you can see the duration rolling as clip plays

I would like to see the timecode as it is represtend on the video in below link

https://vimeo.com/374343428

so the final out come will be 00:00:03:17 (the 17 will be represented in the frames)

Again thank you so much

You want to be formatted zero hours and zero minutes as 00:00 ? To be presented zeroes?

Yes

So if the video was 1 hour 3 minutes 10sec and 17 frames it will be shown as 01:03:10:17

Or if the video was 1 minute 12 sec and 2 frames it would be shown as 00:01:12:02

If the video was 2 minute 5 seconds and 10 frames it would be shown as 00:02:05:10

As here?


use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use framework "AVFoundation"
use scripting additions

-- get files
set theFolder to choose folder
set theURL to current application's |NSURL|'s fileURLWithPath:(POSIX path of theFolder)
set fileManager to current application's NSFileManager's defaultManager()
set {theFiles, theError} to fileManager's contentsOfDirectoryAtURL:theURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(reference)
-- eliminate non-video files
set thePred to current application's NSPredicate's predicateWithFormat:"pathExtension IN %@" argumentArray:{{"mp4", "mov", "webm"}}
set vidFiles to theFiles's filteredArrayUsingPredicate:thePred

-- set up results array, formatter for duration
set theResults to current application's NSMutableArray's array()

-- lop through
repeat with aFile in vidFiles
	-- get localized name
	set {theResult, theName, theError} to (aFile's getResourceValue:(reference) forKey:(current application's NSURLLocalizedNameKey) |error|:(reference))
	-- create an AVAsset so you can get duration
	set theAsset to (current application's AVURLAsset's assetWithURL:aFile)
	set durationInfo to theAsset's duration() -- returns record like: {value:2911360, timescale:1000, flags:1, epoch:0}
	
	if durationInfo is missing value then
		set theTime to "unknown"
		set framesNumber to "unknown"
	else
		-- calculate duration in seconds and format as string
		set theSeconds to (value of durationInfo) / (timescale of durationInfo)
		
		-- Determine frames number here
		set theTracks to (get theAsset's tracks())
		repeat with i from 1 to count theTracks
			set aTrack to item i of theTracks
			if (aTrack's mediaType()) as string is "vide" then exit repeat
		end repeat
		set videoTrack to aTrack
		set frameRate to videoTrack's nominalFrameRate()
		set framesNumber to round ((theSeconds * frameRate) - (round (theSeconds * frameRate) rounding down))
	end if
	
	if framesNumber < 10 then
		set aDuration to (secondsToHMS from (round theSeconds rounding down)) & ":0" & framesNumber
	else
		set aDuration to (secondsToHMS from (round theSeconds rounding down)) & ":" & framesNumber
	end if
	(theResults's addObject:(current application's NSString's stringWithFormat_("%@    %@", theName's stringByDeletingPathExtension(), aDuration)))
end repeat

set aText to (theResults's componentsJoinedByString:linefeed) as text

tell application "Finder" to set folderName to name of theFolder
set filepath to (POSIX path of theFolder) & folderName & ".txt"
set openfile to open for access filepath with write permission
set eof of openfile to 0
write aText as «class utf8» to openfile
close access openfile

on secondsToHMS from theSeconds
	tell theSeconds
		tell {it div hours, it mod hours div minutes, it mod minutes}
			return "" & ((item 1) div 10) & ((item 1) mod 10) & ":" & ((item 2) div 10) & ((item 2) mod 10) & ":" & ((item 3) div 10) & ((item 3) mod 10)
		end tell
	end tell
end secondsToHMS

RESULT: —> file_example_MP4_1920_18MG 00:00:31:00

I tested with 1 mp4 file in the chosen folder

Thank you

Thank you everything works perfect except the frames :frowning:

it still doesn’t represent the frames I am looking for

I have noticed get info in Mac rounds off the frames to closest second instead of showing the frames

I don’t want it to round off the frame but show the actual frame number

For get info to round off the second from the frames it must be receiving that information

If you download the video I sent via Vimeo then the final timecode you see on the video would be
00:00:03:17 . The script now sees that clips duration as 00:00:04:00

I would like it show the actual duration of 00:00:03:17

I updated the last script as found 1 error. Need rounding down instead of rounding as integer. Try now.

NOTE: I can’t download your video from Vimeo

Yes sorry I haven’t explained myself properly

I don’t want it round down or round off

Want the frame number that get info doesn’t show

if the frame rate is 25fps then the timecode will roll over to the next second after the 24 frame

everything is great except I don’t see the frames

if you download the Vimeo linked video I sent and get 00:00:03:17 that timecode from the script then that is what I am trying to achieve

That is the exact duration of the video clip

Ultimately that’s what I am trying to get … the exact duration down to the frame of the video in the folder

I updated the script. You tried it? As I see, no. My script rounds as it is necessary, because doesn’t exist half frame or 1.3 frame, but exists 1 frame, or 2 frames. It is integer value. And script shows it now. Get info rounds to nearest second, but my script rounds to the nearest whole number of frames. As it should be.

And I repeat, I can’t download your Vimeo file to test. I already said that above.

So, open the last script from here and run. Not the script you have on your computer but that updated script from here. Say what you get in the text file.

Sorry I missed the part you said you couldn’t download video file , my bad

Below is the result is get from the .txt file

TEST2_1 00:04:21:00
TEST1_1 00:02:09:00
Comp 1 00:00:03:00
TEST3_1 00:01:38:01

When I take each video files into editing software and look at actual duration they are as follows

TEST2_1 00:04:21:05
TEST1_1 00:02:09:11
Comp 1 00:00:03:17
TEST3_1 00:01:38:03

I was aking is your script rounding off the frame to the nearest 0 , is that’s why all frames are displayed as 00 instead of the frame number of the file ?

the minute and seconds are displayed perfectly but the frames are not

when you had the frames of the entire duration displayed in previous script and I took that into frame calculator that converted back to (hh)(mm)(ss)(ff) it covered to exact timecode

Thank you for you time and effort into trying to help me figure this out