Archive for the 'AVAudioPlayer' Category

2018/01/18 テキストをTTSで読み上げて所要時間を算出 v2.1(CotEditor版)

CotEditorでオープン中の最前面の書類の本文テキストを取得し、macOS標準搭載のText To Speechの機能を用いて最大限に遅い速度(180 words per minute)と速い速度(220 words per minute)の2通りで読み上げて音声読み上げ所要時間のシミュレーション結果をCotEditor内蔵のコンソールに出力するAppleScriptです。

実際の読み上げ時間よりもはるかに短い時間でファイルへの音声レンダリングを実行し、生成した音声ファイルの再生時間(Duration)を取得することで、TTS読み上げ所要時間≒人間が実際に読み上げたときの所要時間を求めます。また、シミュレーション中は音声をファイルに出力するため、スピーカーなどから音声を出すわけではありません。

ttsreadout.png

CotEditor内蔵のScript Menuに入れて実行できることを確認しました。当然、OS側のScript Menuに入れて実行できます。

6,200文字の日本語テキストの読み上げ実時間の計測(速いパターンと遅いパターンの2回実行)に30秒ほどかかりました。読み上げ実時間は15分ぐらいだったので、実時間よりは速く処理できますが、割と時間がかかる処理です。

また、これは「言うは易し、行うは・・・」の典型例のような処理でした。sayコマンドによるTTS読み上げ、音声のファイル出力、読み上げ実時間を待たずにサウンドファイル出力などの機能がありながら、これらが非同期で実行されるために骨が折れます。

出力ファイルの再生時間を取得しようとするとエラー、出力ファイルパスのPOSIX pathにquoted form of でクォート処理するとエラー、などなど。

とりあえず、sayコマンドによる音声ファイル出力が終わったあと、音声ファイルが本当に出力終了するまでファイルをチェックしつつ待ちます。sayコマンドからの出力が並列処理で行えれば、並列処理向きの内容だと思います。

CotEditor以外でも実際にAppleScriptに対応しているエディタであれば、本文テキストを取得するだけなのでテキストエディットをはじめだいたいのものには対応できます。

AppleScript名:テキストをTTSで読み上げて所要時間を算出 v2.1(CotEditor版)
– Created 2018-01-10 by Takaaki Naganoya
– 2018 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AVFoundation”
use framework “AppKit”
–http://piyocast.com/as/archives/5113

property |NSURL| : a reference to current application’s |NSURL|
property NSDate : a reference to current application’s NSDate
property NSUUID : a reference to current application’s NSUUID
property NSFileManager : a reference to current application’s NSFileManager
property AVAudioPlayer : a reference to current application’s AVAudioPlayer
property NSDateFormatter : a reference to current application’s NSDateFormatter
property NSSpeechSynthesizer : a reference to current application’s NSSpeechSynthesizer

set str3 to getEditorText() of me
if str3 = false then return

set aVoice to “Kyoko”

–Check existence of TTS Voice name
set vList to retAvailableTTSnames() of me
if aVoice is not in vList then error “Wrong TTS Voice Name”

set d1 to readTextByTTSVoiceAndReturnDuration(str3, aVoice, 180) of me –aSpeedRate is “Words per minute. 180 to 220″
set d2 to readTextByTTSVoiceAndReturnDuration(str3, aVoice, 220) of me

set outStr to (formatHMS(d1) of me & “/180 words per minute”) & return & (formatHMS(d2) of me & “/220 words per minute”) & return
tell application “CotEditor”
  activate
  
write to console outStr
end tell

on readTextByTTSVoiceAndReturnDuration(aStr as string, aVoice as string, aSpeedRate as integer)
  set aUUID to NSUUID’s UUID()’s UUIDString() as string
  
–set aPath to (((path to temporary items from user domain) as string) & aUUID & “.aif”)
  
set aPath to (((path to desktop) as string) & aUUID & “.aif”)
  
set aPOSIX to POSIX path of aPath
  
  
tell current application
    say aStr using aVoice saving to (aPOSIX) speaking rate aSpeedRate without waiting until completion
  end tell
  
  
repeat 100000 times
    set aExt to NSFileManager’s defaultManager()’s fileExistsAtPath:aPOSIX
    
if aExt as boolean = true then exit repeat
    
delay “0.001″ as real
  end repeat
  
  
if aExt = false then error “No Sound file”
  
  
set aDur to getDuration(aPath as alias) of me
  
try
    do shell script “rm -f “ & quoted form of POSIX path of aPath
  end try
  
  
return aDur as real
end readTextByTTSVoiceAndReturnDuration

on getDuration(aFile)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of aFile)
  
  
repeat 1000 times
    set aAudioPlayer to AVAudioPlayer’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
    
set aRes to aAudioPlayer’s prepareToPlay()
    
if aRes as boolean = true then exit repeat
    
delay 0.5
  end repeat
  
if aRes = false then error “TTS sound output failed”
  
  
set channelCount to aAudioPlayer’s numberOfChannels()
  
set aDuration to aAudioPlayer’s duration()
  
return aDuration as real
end getDuration

on retAvailableTTSnames()
  set outList to {}
  
  
set aList to NSSpeechSynthesizer’s availableVoices()
  
set bList to aList as list
  
  
repeat with i in bList
    set j to contents of i
    
set aInfo to (NSSpeechSynthesizer’s attributesForVoice:j)
    
set aInfoRec to aInfo as record
    
set aName to VoiceName of aInfoRec
    
set the end of outList to aName
  end repeat
  
  
return outList
end retAvailableTTSnames

on formatHMS(aTime)
  set aDate to NSDate’s dateWithTimeIntervalSince1970:aTime
  
set aFormatter to NSDateFormatter’s alloc()’s init()
  
  
—This formatter text is localized in Japanese.
  
if aTime < hours then
    aFormatter’s setDateFormat:“mm分ss秒”
  else if aTime < days then
    aFormatter’s setDateFormat:“HH時間mm分ss秒”
  else
    aFormatter’s setDateFormat:“DD日HH時間mm分ss秒”
  end if
  
  
set timeStr to (aFormatter’s stringFromDate:aDate) as string
  
return timeStr
end formatHMS

on getEditorText()
  tell application “CotEditor”
    if (count every document) = 0 then return false
    
tell front document
      return contents
    end tell
  end tell
end getEditorText

★Click Here to Open This Script 

2014/12/25 オーディオファイルのチャンネル数と再生時間を取得する

オーディオファイル(QuickTime Playerによるオーディオ収録ファイル、m4a)から情報を取得するAppleScriptです。

オーディオチャンネル数と、duration(再生時間:秒)を取得します。

AVAudioPlayerについては、playAtTime:がうまく動かなくて悩んでいます、、、

AppleScript名:オーディオファイルのチャンネル数と再生時間を取得する
– Created 2014-12-25 by Takaaki Naganoya
– 2014 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “AVFoundation”

set a to choose file of type {“com.apple.m4a-audio”}
set aURL to (current application’s SMSFord’s URLFrom:a)

set aAudioPlayer to current application’s AVAudioPlayer’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
aAudioPlayer’s prepareToPlay()

set channelCount to aAudioPlayer’s numberOfChannels()
log {“channelCount”, channelCount}

set aDuration to aAudioPlayer’s duration()
–> 7355.9873015873 (Unit:Second)

★Click Here to Open This Script