Objective-C
iOS
Swift
WatchKit
watchOS

watchOS 2 のオーディオ録音、再生機能を利用する

More than 3 years have passed since last update.

以前から音声からのテキスト入力機能(Dectation)として Apple Watch のマイクを利用することはできましたが、watchOS 2 より、WKInterfaceController に新たに 音声を録音してファイル出力する UI を表示するメソッドが追加されました。

func presentAudioRecordingControllerWithOutputURL(_ URL: NSURL,

preset preset: WKAudioRecordingPreset,
maximumDuration maximumDuration: NSTimeInterval,
actionTitle actionTitle: String?,
completion completion: (Bool,
NSError?) -> Void)

こんな感じの UI で録音することができます。

recorder.jpg

(公開されているWWDCセッションの動画より)


実装方法


Swift

まず、オーディオファイルを出力する先の NSURL オブジェクトを生成しておきます。

let filePaths = NSSearchPathForDirectoriesInDomains(

NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomainMask.UserDomainMask,
true)
let documentDir = filePaths.first!
let filePath = documentDir + "rec.m4a"
let fileUrl = NSURL.fileURLWithPath(filePath)

ファイルの拡張子は .wav, .mp4, .m4a が指定でき、これが録音するオーディオのタイプを決定します。

presentAudioRecordingControllerWithOutputURL:preset:maximumDuration:actionTitle:completion: メソッドを次のように呼びます。

self.presentAudioRecordingControllerWithOutputURL(

fileUrl,
preset: WKAudioRecordingPreset.WideBandSpeech,
maximumDuration: 5.0,
actionTitle: "SomeTitle") { (didSave, error) -> Void in

print("didSave:\(didSave), error:\(error)")
}

第2引数の preset は録音品質を指定するもので、上記以外に NarrowBandSpeech, HighQualityAudio を渡せます。


Objective-C

ちなみに ObjC で書くとこんな感じです。

NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,

NSUserDomainMask,YES);
NSString *path = [[filePaths firstObject] stringByAppendingPathComponent:@"rec.m4a"];
NSURL *fileUrl = [NSURL fileURLWithPath:path];

[self presentAudioRecordingControllerWithOutputURL:fileUrl

preset:WKAudioRecordingPresetWideBandSpeech
maximumDuration:5.0
actionTitle:@"Some Title"
completion:^(BOOL didSave, NSError * __nullable error) {

NSLog(@"didSave:%d, error:%@", didSave, error);
}];


再生

オーディオやビデオファイルを再生する UI を表示するメソッドも新たに追加されました。次のように、メディアファイルの NSURL オブジェクトを渡すだけ。

self.presentMediaPlayerControllerWithURL(

fileURL,
options: nil) { (didPlayToEnd, endTime, error) -> Void in

print("didPlayToEnd:\(didPlayToEnd), endTime:\(endTime), error:\(error)")
}

前述した presentAudioRecording〜 で録音したファイルなら、そのとき渡した NSURL オブジェクトをそのままこっちのメソッドに渡すだけです。

こんな感じのUIが表示されます。

player.jpg

(一般公開されているWWDCの動画より)


WKAudioFilePlayer

WKAudioPlayer を利用すると、 Watch とペアリングされた Bluetooth オーディオヘッドセットでのオーディオファイル再生 が可能となります。

プロパティを定義しておいて、

var player: WKAudioFilePlayer!

こんな感じで、WKAudioFileAsset → WKAudioFilePlayerItem → WKAudioFilePlayer を作成します。

override func awakeWithContext(context: AnyObject?) {

super.awakeWithContext(context)

let filePath = NSBundle.mainBundle().pathForResource("se_tap", ofType: "m4a")!
let fileUrl = NSURL.fileURLWithPath(filePath)
let asset = WKAudioFileAsset(URL: fileUrl)
let playerItem = WKAudioFilePlayerItem(asset: asset)
player = WKAudioFilePlayer(playerItem: playerItem)
}

再生は play メソッドを呼ぶだけですが、status.ReadyToPlay になってないといけないので、こんな感じにしてみました。

@IBAction func playBtnTapped() {

switch player.status {
case .ReadyToPlay:
player.play()
case .Failed:
label.setText("failed")
case .Unknown:
label.setText("unknown")
}
}

(実際には status が .ReadyToPlay になるまでタイマーでポーリングすべき?delegateみたいなのとか、再生準備完了の通知みたいなのは見当たらなかった。WKAudioFilePlayerItem にはいくつかの関連する通知があるみたいだけど。)

ちなみに WKAudioPlayer は、ひとつのオーディオファイル再生用です。複数のオーディオファイルを再生したい場合は、WKAudioFileQueuePlayer を利用します。


参考資料(ログイン不要領域にて利用可能)