質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

3959閲覧

swift:AVAudioRecoderの使い方がわかりません

退会済みユーザー

退会済みユーザー

総合スコア0

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/06/14 10:18

編集2017/06/18 05:00

#環境
swift3.1
xcode8.3.3

#質問内容
最近swiftを始めました。
AVFoundationのAVRecoderを使ってMAC上で音声を録音するプログラムを書きたいのですが、公式のドキュメントを読んでも具体的な手順がいまいちよくわかりません。
YouTubeで、iOS版の動画があったので参考になるかと思い見てみたのですが、疑問点が多く生まれてしまいました。。。

#疑問点
動画の一部

1つめ
この画像はAudioRecoderManagerという名前のNSObjectのサブクラスを作成している部分だと思うんですが、
16行目:

swift

1static let shared = AudioRecoderManager()

これって自分(self)をインスタンス化してるんですか?そんなことができるのでしょうか

2つめ
19行目:

swift

1var recordingSession: AVRecordSession!

と書かれていてこの後もAVRecordSession関係のコードが連なっているのですが、これはAVAudioRecoderの公式ドキュメントに書いてある> To configure an appropriate audio session for recording, refer to AVAudioSession and AVAudioSessionDelegate.
のとおり、任意でのオーディオセッションの設定をしているのでしょうか?これはデフォルトでいい場合書かなくてもいいということですよね?

3つめ
AVAudoiRecoderの初期化
公式ドキュメントによると、AVAudioRecoderを初期化するには保存先URLとsettingsを引数に入れると書いてあるようなのですが、このsettingsという引数に何を書けばいいのかがさっぱりわかりません。
(上の動画ではsettingsをrecordSettingsという配列で書いていますが何を格納してるのかがわかりません)

総括
動画ではスラスラとコーディングしてらっしゃるのですが、どのようにドキュメントを旅すればこのような疑問が生まれることなく明確に(例えばAVAudioRecoderを使った録音のコードの)手順を把握できるのでしょうか。

わかりやすく教えていただけると幸甚の至りです。
初心者ゆえ稚拙な文章になってしまったことをお詫び申し上げます。

#izknさんのコードを改造した結果
5秒録音の部分を、「録音」, 「停止」ボタンを作って制御できるようにしようとした結果

xcode

swift

1recorder.prepareToRecord()

でEXC_BAD_INSTRUCTIONエラーが出ました。
recoderインスタンスのスコープの問題かなと思い、recoderの定義にprivateをつけてみたけれど変わらず。。。
何が起こっているのか......(´・_・`)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

MAC上で音声を録音するプログラムを書きたい

ということで回答します。

1つめ

既に回答されているように、シングルトンですね。

2つめ

本件に関しては忘れても良いです。なぜか...
macOSには、AVAudioSessionはありません。

3つめ

General Audio Format Settings | Apple Developer Documentation
設定する必要がなければ、下記で構いません。

let recordSettings : [String : Any] = [:]

その場合は、このように設定されます。

["AVLinearPCMIsFloatKey": 0, "AVLinearPCMIsNonInterleaved": 0, "AVNumberOfChannelsKey": 1, "AVSampleRateKey": 8000, "AVLinearPCMBitDepthKey": 16, "AVLinearPCMIsBigEndianKey": 0, "AVFormatIDKey": 1819304813]

AVFormatIDKeyについては、以下のリンク、もしくはCoreAudio.framework/CoreAudioTypes.hを参照してください。
Core Audio Data Types | Apple Developer Documentation

Apple Developerにサンプルありますが、ちと大げさすぎますね。
実はそんなに難しいものではなく、結構簡単に書けちゃいます。
ということで、ビルドすると、勝手に5秒録音して、勝手に再生するものを書いてみました。

macOSCocoa Applicationを選んで、ViewController.swiftに貼り付けるだけ。
動かなくても、保証はしませんよ。では良い開発を ノシ

import Cocoa import AVFoundation class ViewController: NSViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate { var recorder: AVAudioRecorder! var player: AVAudioPlayer! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let recordingUrl = documentDirectory.appendingPathComponent("recording.caf") let recordSettings : [String : Any] = [:] // let recordingUrl = documentDirectory.appendingPathComponent("recording.m4a") // let recordSettings : [String : Any] = [ // AVFormatIDKey: UInt(kAudioFormatMPEG4AAC), // AVSampleRateKey: 44100.0, // AVNumberOfChannelsKey: 2 // ] do { recorder = try AVAudioRecorder(url: recordingUrl, settings: recordSettings) recorder.delegate = self recorder.prepareToRecord() print(recorder.settings as Any) recorder.record(forDuration: 5.0) // recorder.stop() } catch { recorder = nil } } func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { print("録音終了") let recordingUrl = recorder.url do { player = try AVAudioPlayer(contentsOf: recordingUrl, fileTypeHint: nil) player.delegate = self; print("再生時間: \(player.duration)") player.volume = 1.0 player.play() } catch { } } func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) { print(error!) } func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { print("再生終了") } func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) { print(error!) } override var representedObject: Any? { didSet { // Update the view, if already loaded. } } }

###追記

関数名に書かれているようなタイミングで処理されるのでしょうか。(audioRecorderDidFinishRecordingならレコードが終了したときでしょうか。)

はい。そのタイミングで呼ばれるものですね。

イベント系の関数はoverrideするものだとばかり思っていたのですが

そもそもこいつらは一体何者なんでしょうか。AVAudioRecorderDelegateAVAudioPlayerDelegateのメソッドです。

では、AVAudioRecorderDelegateとは何なのかというと、クラスではなく、プロトコルです。つまり定義です。
以下、AVFoundation.framework/Frameworks/AVFAudio.framework/Headers/AVAudioRecorder.hより抜粋

/* A protocol for delegates of AVAudioRecorder */ __TVOS_UNAVAILABLE __WATCHOS_PROHIBITED @protocol AVAudioRecorderDelegate <NSObject> @optional /* audioRecorderDidFinishRecording:successfully: is called when a recording has been finished or stopped. This method is NOT called if the recorder is stopped due to an interruption. */ - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag; /* if an error occurs while encoding it will be reported to the delegate. */ - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * __nullable)error;

ViewControllerクラスのfunc audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool)などでようやく処理が実装されました。そのため、overrideは付きません。

###追記2
悲しいお知らせです。AVAudioRecordermp3形式で録音できません。

swift

1recoder = try AVAudioRecorder(url: recodingUrl, settings: recordSettings)

この時点で形式等に問題があれば、キャッチしてくれています。見ても何の事やらですが。

caf形式か,iTunesで開きたいというのであればm4a形式を使ってください。
最低限AVFormatIDKeyは必要です。

swift

1let recodingUrl = documentDirectory.appendingPathComponent("result.m4a", isDirectory: false) 2let recordSettings : [String : Any] = [ 3 AVFormatIDKey: UInt(kAudioFormatMPEG4AAC) 4]

次からは新規で質問立ててくださいね。その方が早く回答もつくでしょうから。
では、良い開発を ノシ

投稿2017/06/15 08:25

編集2017/06/18 07:52
izkn

総合スコア1698

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/15 15:15

3つめに対する詳しい解説に加え、サンプルコードまで提示していただき、本当に頭が下がる思いです。 appkitについての情報があまりにも少ないため、これからもAVFoundation周りについてTERATAIL様にお世話になるかと思いますが、その際も御知恵を貸していただけると幸いです。。
退会済みユーザー

退会済みユーザー

2017/06/17 05:11

サンプルコードについての質問なのですが、audioRecorderDidFinishRecording, audioRecorderEncodeErrorDidOccur, audioPlayerDidFinishPlaying, audioPlayerDecodeErrorDidOccurはどこにも呼び出されていないのですが、関数名に書かれているようなタイミングで処理されるのでしょうか。(audioRecorderDidFinishRecordingならレコードが終了したときでしょうか。) イベント系の関数はoverrideするものだとばかり思っていたのですが
guest

0

1つめ

シングルトン(singleton)について調べて下さい。

2つめ

とりあえずパスですが、「設定しなければデフォルト設定」と書かれているようには見えません。(英語弱いです)まぁ、一度試してみたら分かるでしょう。

3つめ

__AV Foundation Audio Settings Constants__を見ろと書いてありますが、見ましたか?
私は見つけられませんでしたw
ググれば少しですが情報は見つかります。

投稿2017/06/15 00:39

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/15 08:19

回答ありがとうございます! シングルトンというものみたいですね、ありがとうございます デフォルトとは書かれてませんでした。間違っていました。AVAudioRecoderを使うための手順の一つだったようですね。 AV Foundation Audio Settings Constantsはもちろん検索しましたがヒットせず、明確な答えが見つかりませんでした。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問