| 001 | #!/usr/bin/env osascript |
| 002 | #coding: utf-8 |
| 003 | ----+----1----+----2----+-----3----+----4----+----5----+----6----+----7 |
| 004 | (* |
| 005 |
|
| 006 | ffmpegのパスはご自身の環境にあわせて変更してください |
| 007 |
|
| 008 |
|
| 009 | com.cocolog-nifty.quicktimer.icefloe *) |
| 010 | ----+----1----+----2----+-----3----+----4----+----5----+----6----+----7 |
| 011 | ##自分環境がos12なので2.8にしているだけです |
| 012 | use AppleScript version "2.8" |
| 013 | use framework "Foundation" |
| 014 | use framework "AVFoundation" |
| 015 | use framework "AppKit" |
| 016 | use framework "UniformTypeIdentifiers" |
| 017 | use scripting additions |
| 018 |
|
| 019 | property refMe : a reference to current application |
| 020 | set appFileManager to refMe's NSFileManager's defaultManager() |
| 021 |
|
| 022 | ############################# |
| 023 | #【設定項目】 ffmpegへのパス |
| 024 | set strFFMPEGFilePath to ("~/Library/Application Support/bin/ffmpeg/ffmpeg") as text |
| 025 | set ocidBinPathStr to refMe's NSString's stringWithString:(strFFMPEGFilePath) |
| 026 | set ocidBinPath to ocidBinPathStr's stringByStandardizingPath() |
| 027 | set strFFMPEGFilePath to ocidBinPath as text |
| 028 |
|
| 029 | ############################# |
| 030 | #書き出しファイルの保存先 |
| 031 | set ocidURLsArray to (appFileManager's URLsForDirectory:(refMe's NSMoviesDirectory) inDomains:(refMe's NSUserDomainMask)) |
| 032 | set ocidMoviesDirPathURL to ocidURLsArray's firstObject() |
| 033 | set ocidSaveDirPathURL to ocidMoviesDirPathURL's URLByAppendingPathComponent:("AVAssetExport") |
| 034 | set ocidAttrDict to refMe's NSMutableDictionary's alloc()'s initWithCapacity:0 |
| 035 | ocidAttrDict's setValue:(448) forKey:(refMe's NSFilePosixPermissions) |
| 036 | set listDone to appFileManager's createDirectoryAtURL:(ocidSaveDirPathURL) withIntermediateDirectories:true attributes:(ocidAttrDict) |error|:(reference) |
| 037 |
|
| 038 | ############################# |
| 039 | #テンポラリー |
| 040 | set appFileManager to refMe's NSFileManager's defaultManager() |
| 041 | set ocidTempDirURL to appFileManager's temporaryDirectory() |
| 042 | set ocidUUID to refMe's NSUUID's alloc()'s init() |
| 043 | set ocidUUIDString to ocidUUID's UUIDString |
| 044 | set ocidTmpDirPathURL to ocidTempDirURL's URLByAppendingPathComponent:(ocidUUIDString) isDirectory:true |
| 045 | set listDone to appFileManager's createDirectoryAtURL:(ocidTmpDirPathURL) withIntermediateDirectories:true attributes:(ocidAttrDict) |error|:(reference) |
| 046 |
|
| 047 | ############################# |
| 048 | ###入力ファイル |
| 049 | ############################# |
| 050 | tell current application |
| 051 | set strName to name as text |
| 052 | end tell |
| 053 | if strName is "osascript" then |
| 054 | tell application "SystemUIServer" to activate |
| 055 | else |
| 056 | tell current application to activate |
| 057 | end if |
| 058 | #デスクトップ |
| 059 | set appFileManager to refMe's NSFileManager's defaultManager() |
| 060 | set ocidURLsArray to (appFileManager's URLsForDirectory:(refMe's NSDesktopDirectory) inDomains:(refMe's NSUserDomainMask)) |
| 061 | set ocidDesktopDirPathURL to ocidURLsArray's firstObject() |
| 062 | set aliasDesktopDirPath to (ocidDesktopDirPathURL's absoluteURL()) as alias |
| 063 | set listUTI to {"public.movie", "com.microsoft.advanced-systems-format"} as list |
| 064 | tell application "SystemUIServer" |
| 065 | activate |
| 066 | set aliasFilePath to (choose file with prompt "ムービーファイルを選んでください" default location (aliasDesktopDirPath) of type listUTI with invisibles and showing package contents without multiple selections allowed) as list |
| 067 | end tell |
| 068 |
|
| 069 |
|
| 070 | ############################# |
| 071 | #本処理 |
| 072 | ###入力ファイル |
| 073 |
|
| 074 | set strFilePath to (POSIX path of aliasFilePath) as text |
| 075 | set ocidFilePathStr to (refMe's NSString's stringWithString:(strFilePath)) |
| 076 | set ocidFilePath to ocidFilePathStr's stringByStandardizingPath() |
| 077 | set ocidFilePathURL to (refMe's NSURL's alloc()'s initFileURLWithPath:(ocidFilePath) isDirectory:false) |
| 078 | set ocidFileName to ocidFilePath's lastPathComponent() |
| 079 | set ocidBaseFileName to ocidFileName's stringByDeletingPathExtension() |
| 080 | ###上書きチェック |
| 081 | set numCnt to 0 as number |
| 082 | set strSaveFileName to (ocidBaseFileName's stringByAppendingPathExtension:("mp4")) |
| 083 | repeat 100 times |
| 084 | ###保存先URL |
| 085 | set ocidSaveFilePathURL to (ocidSaveDirPathURL's URLByAppendingPathComponent:(strSaveFileName)) |
| 086 | set ocidSaveFilePath to ocidSaveFilePathURL's |path|() |
| 087 | set boolExist to (appFileManager's fileExistsAtPath:(ocidSaveFilePath) isDirectory:(false)) |
| 088 | ## |
| 089 | if boolExist is true then |
| 090 | set numCnt to numCnt + 1 as number |
| 091 | set strZeroSup to "000" as text |
| 092 | set strZeroSup to (strZeroSup & (numCnt as text)) as text |
| 093 | set strZeroSup to (text -3 through -1 of strZeroSup) as text |
| 094 | set strZeroSupFileName to (ocidBaseFileName's stringByAppendingPathExtension:(strZeroSup)) |
| 095 | set strSaveFileName to (strZeroSupFileName's stringByAppendingPathExtension:("mp4")) |
| 096 | else |
| 097 | log "保存先パス: " & ocidSaveFilePath as text |
| 098 | exit repeat |
| 099 | end if |
| 100 | end repeat |
| 101 | set strSaveFilePath to ocidSaveFilePath as text |
| 102 | ############################# |
| 103 | ### ビデオの情報取得 |
| 104 | ############################# |
| 105 | set ocidOptionDict to refMe's NSMutableDictionary's alloc()'s init() |
| 106 | (ocidOptionDict's setObject:(true) forKey:(refMe's AVURLAssetPreferPreciseDurationAndTimingKey)) |
| 107 | (ocidOptionDict's setObject:(false) forKey:(refMe's AVURLAssetAllowsCellularAccessKey)) |
| 108 | (ocidOptionDict's setObject:(true) forKey:(refMe's AVURLAssetAllowsConstrainedNetworkAccessKey)) |
| 109 | (ocidOptionDict's setObject:(refMe's AVAssetReferenceRestrictionForbidAll) forKey:(refMe's AVAssetReferenceRestrictions)) |
| 110 | (ocidOptionDict's setObject:(true) forKey:(refMe's AVURLAssetURLRequestAttributionKey)) |
| 111 | set ocidReadAsset to (refMe's AVURLAsset's alloc()'s initWithURL:(ocidFilePathURL) options:(ocidOptionDict)) |
| 112 | # |
| 113 | set ocidVideoAssetTrack to (ocidReadAsset's tracksWithMediaType:(refMe's AVMediaTypeVideo)) |
| 114 | set ocidReadAssetTrackArray to ocidReadAsset's tracks() |
| 115 | set ocidVideoTrack to ocidReadAssetTrackArray's firstObject() |
| 116 | if ocidVideoTrack = (missing value) then |
| 117 | log ocidFilePathURL's |path| as text |
| 118 | return "構造が不正なビデオがあります" |
| 119 | end if |
| 120 | #サイズを取得 |
| 121 | set recordAssetTrackNaturalSize to ocidVideoTrack's naturalSize() |
| 122 | set numW to (width of recordAssetTrackNaturalSize) |
| 123 | set numH to (height of recordAssetTrackNaturalSize) |
| 124 | if numW = 0 then |
| 125 | set numSetW to 1280 as integer |
| 126 | set numSetH to 720 as integer |
| 127 | else |
| 128 | set numResolution to (numW / numH) as number |
| 129 | set numSetH to 720 as integer |
| 130 | set numSetW to (numSetH * numResolution) as integer |
| 131 | #偶数処理 |
| 132 | #整数部を求めて |
| 133 | set numRoundNo to (round of numSetW rounding down) as integer |
| 134 | #2で割って割り切れるか?を確認 |
| 135 | set numChkEven to (numRoundNo mod 2) as integer |
| 136 | #判定 |
| 137 | if numChkEven = 0 then |
| 138 | #あまり無しなら偶数なので整数部を戻す |
| 139 | set numSetW to numRoundNo as integer |
| 140 | else if numChkEven > 0 then |
| 141 | #あまりがあるなら奇数なので1加えて戻す |
| 142 | set numSetW to (numRoundNo + 1) as integer |
| 143 | end if |
| 144 | end if |
| 145 |
|
| 146 | ###### h264_videotoolbox |
| 147 | set strCmd to ("\"" & strFFMPEGFilePath & "\" -i \"" & strFilePath & "\" -codec:v h264_videotoolbox -profile:v main -b:v 2M -q:v 40 -maxrate 2M -bufsize 1M -g 120 -pix_fmt yuv420p -level 4.1 -vf \"scale=" & numSetW & ":720:force_original_aspect_ratio=increase,crop=" & numSetW & ":720\" -movflags +faststart -video_track_timescale 1000 -codec:a aac -ar 12000 -b:a 128K -allow_sw 1 \"" & strSaveFilePath & "\"") as text |
| 148 |
|
| 149 | log return & strCmd & return |
| 150 |
|
| 151 | set strDone to doExecZsh(strCmd) |
| 152 | if strDone is true then |
| 153 | log "正常終了" |
| 154 | else |
| 155 | log "エラーになりました" |
| 156 | end if |
| 157 |
|
| 158 |
|
| 159 | ################################ |
| 160 | #ファイル保存先を開く |
| 161 | set aliasSaveDirFilePath to (ocidSaveDirPathURL's absoluteURL()) as alias |
| 162 | tell application "Finder" |
| 163 | open aliasSaveDirFilePath |
| 164 | end tell |
| 165 |
|
| 166 | return |
| 167 |
|
| 168 |
|
| 169 | ################################ |
| 170 | #経過時間計算 |
| 171 | to doGetTimeInderval(argStartTime) |
| 172 | #今の時間 |
| 173 | set ocidEndTime to refMe's NSDate's |date|() |
| 174 | #渡されたスタート時間からの間隔を取得 |
| 175 | set numIntervalSec to ocidEndTime's timeIntervalSinceDate:(argStartTime) |
| 176 | #戻り値が秒数値なので時間にする |
| 177 | set numH to (numIntervalSec / 3600) as integer |
| 178 | set numM to ((numIntervalSec - (numH * 3600)) / 60) as integer |
| 179 | set numS to (numIntervalSec - (numH * 3600) - (numM * 60)) as integer |
| 180 | #2桁テキストにして |
| 181 | set appFormatter to refMe's NSNumberFormatter's alloc()'s init() |
| 182 | appFormatter's setMinimumIntegerDigits:(2) |
| 183 | appFormatter's setPaddingCharacter:("0") |
| 184 | appFormatter's setPaddingPosition:(refMe's NSNumberFormatterPadBeforePrefix) |
| 185 | set strH to (appFormatter's stringFromNumber:(numH)) as text |
| 186 | set strM to (appFormatter's stringFromNumber:(numM)) as text |
| 187 | set strS to (appFormatter's stringFromNumber:(numS)) as text |
| 188 | #戻り値用整形 |
| 189 | set strInterval to (strH & ":" & strM & ":" & strS) as text |
| 190 | return strInterval |
| 191 | end doGetTimeInderval |
| 192 |
|
| 193 |
|
| 194 | ################################ |
| 195 | # 今の日付日間 テキスト |
| 196 | to doGetDateNo(argDateFormat) |
| 197 | ####日付情報の取得 |
| 198 | set ocidDate to current application's NSDate's |date|() |
| 199 | ###日付のフォーマットを定義 |
| 200 | set ocidNSDateFormatter to current application's NSDateFormatter's alloc()'s init() |
| 201 | set ocidLocale to current application's NSLocale's localeWithLocaleIdentifier:("ja_JP_POSIX") |
| 202 | ocidNSDateFormatter's setLocale:(ocidLocale) |
| 203 | set ocidTimeZone to current application's NSTimeZone's alloc()'s initWithName:("Asia/Tokyo") |
| 204 | ocidNSDateFormatter's setTimeZone:(ocidTimeZone) |
| 205 | ocidNSDateFormatter's setDateFormat:(argDateFormat) |
| 206 | set ocidDateAndTime to ocidNSDateFormatter's stringFromDate:(ocidDate) |
| 207 | set strDateAndTime to ocidDateAndTime as text |
| 208 | return strDateAndTime |
| 209 | end doGetDateNo |
| 210 |
|
| 211 |
|
| 212 | ################################ |
| 213 | #タスク実行 |
| 214 | to doExecZsh(argCommandText) |
| 215 | log "開始:" & doGetDateNo("yyyyMMdd hhmmss") |
| 216 | set ocidStartTime to refMe's NSDate's |date|() |
| 217 | |
| 218 | #起動 新規タブ |
| 219 | tell application "Terminal" |
| 220 | set objWindowID to (do script "" & return & return & "") |
| 221 | end tell |
| 222 | |
| 223 | #起動待ち |
| 224 | repeat 10 times |
| 225 | delay 1 |
| 226 | tell application "Terminal" |
| 227 | set boolFrontmost to frontmost as boolean |
| 228 | end tell |
| 229 | if boolFrontmost is false then |
| 230 | tell application "Terminal" to activate |
| 231 | else if boolFrontmost is true then |
| 232 | exit repeat |
| 233 | end if |
| 234 | end repeat |
| 235 | |
| 236 | #コマンド実行 |
| 237 | tell application "Terminal" |
| 238 | do script argCommandText in objWindowID |
| 239 | end tell |
| 240 | |
| 241 | #コマンドが走るの待ち |
| 242 | repeat 10 times |
| 243 | delay 1 |
| 244 | tell application "Terminal" |
| 245 | tell objWindowID |
| 246 | set numCntProcesses to (count of processes) as integer |
| 247 | end tell |
| 248 | end tell |
| 249 | if numCntProcesses > 2 then |
| 250 | exit repeat |
| 251 | end if |
| 252 | end repeat |
| 253 | |
| 254 | |
| 255 | |
| 256 | ################################ |
| 257 | #ここから終了待ち処理 |
| 258 | repeat |
| 259 | (* |
| 260 | アクティベート 前面に出す処理をやめた |
| 261 | tell application "Terminal" |
| 262 | activate |
| 263 | tell objWindowID |
| 264 | activate |
| 265 | end tell |
| 266 | end tell |
| 267 | *) |
| 268 | |
| 269 | tell application "Terminal" |
| 270 | tell objWindowID |
| 271 | set boolBusy to busy as boolean |
| 272 | end tell |
| 273 | end tell |
| 274 | if boolBusy is true then |
| 275 | #まだ実行中 |
| 276 | #処理中にスリープさせない |
| 277 | do shell script "/usr/bin/caffeinate -u -t 10" |
| 278 | #終了した |
| 279 | end if |
| 280 | tell application "Terminal" |
| 281 | tell objWindowID |
| 282 | set numCntProcesses to (count of processes) as integer |
| 283 | end tell |
| 284 | end tell |
| 285 | if numCntProcesses > 2 then |
| 286 | do shell script "/usr/bin/caffeinate -u -t 10" |
| 287 | else |
| 288 | exit repeat |
| 289 | end if |
| 290 | |
| 291 | end repeat |
| 292 | |
| 293 | |
| 294 | log "終了:" & doGetDateNo("yyyyMMdd hhmmss") |
| 295 | log "経過時間: " & doGetTimeInderval(ocidStartTime) |
| 296 | return true |
| 297 | end doExecZsh |