iPhone SDK:AVAudioRecorder在调用[AVPlayer播放]后不会录音

发布于 2024-10-23 18:40:26 字数 454 浏览 5 评论 0原文

我有一个使用 AVPlayer 的视图控制器。该视图控制器可以加载模态视图控制器,用户可以在其中使用 AVAudioRecorder 录制音频。

这就是发生的情况:

如果用户使用 [AVPLayer play] 在第一个控制器中播放乐曲,AVAudioRecorder 将不会在模态视图控制器中录制。没有错误,但 AVAudioRecorder 返回的当前时间是 0.0;

如果用户关闭模式对话框并重新加载它。 AVAudioRecorder 工作正常。

这可以一遍又一遍地重复 AVAudioRecorder 在 [AVPlayer play] 调用后第一次调用时不起作用,

我已经为此奋斗了好几天,刚刚重新组织了与 AVPlayer 和 AVAudioRecorder 相关的代码,但它仍然表现得很奇怪。

非常感谢任何帮助或指示

提前致谢

Jean-Pierre

I have a view controller that uses AVPlayer. this view controller can load a modal view controler where the user can record audio using AVAudioRecorder.

this is what happens:

if the user plays the composition in the fist controller with [AVPLayer play] the AVAudioRecorder will not record in the modal view controller. there are no errors but the current time returned by AVAudioRecorder is 0.0;

if the user dismisses the modal dialog and reloads it. AVAudioRecorder works fine.

this can be repeated over and over
AVAudioRecorder does not work the first time it is invoked after a [AVPlayer play] call

I have been fighting with this for days and just have reorganized my code related to both AVPlayer and AVAudioRecorder and it's still acting weird.

Any help or pointer is much appreciated

Thanks in advance

Jean-Pierre

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

风筝在阴天搁浅。 2024-10-30 18:40:26

我也遇到了同样的问题,这就是我找到的解决方案。

录音时,在AVAudioRecord初始化后写入这行代码:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:NULL];

然后调用record方法。

I've been having the same problem too, and this is the solution I found.

When recording, write this line code after AVAudioRecord is initialized:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:NULL];

Then invoke record method.

优雅的叶子 2024-10-30 18:40:26

您如何设置 AVAudioSession 的类别,即播放或录制?尝试类似的东西

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

How are you setting the AVAudioSession's category, i.e., play or record? Try something like

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
美人迟暮 2024-10-30 18:40:26

我也遇到了同样的问题。我使用 AVPlayer 来播放乐曲(之前的录音我使用过 AVAudioRecord)。然而,我发现一旦我使用了AVPlayer,我就无法再使用AVAudioRecorder了。经过一番搜索,我发现只要 AVPlayer 在内存中实例化并且至少播放过一次(通常是实例化后立即执行的操作),AVAudioRecorder 就不会录制。然而,一旦 AVPlayer 被释放,AVAudioRecorder 就可以再次自由录制。看来 AVPlayer 保留了 AVAudioRecorder 所需的某种连接,而且它很贪婪......它不会放开它,除非你从它冰冷的死手上撬开它。

这是我找到的解决方案。有些人声称实例化 AVPlayer 需要太多时间来不断崩溃和重新设置。然而,事实并非如此。实例化 AVPlayer 实际上非常简单。实例化 AVPlayerItem 也是如此。加载 AVAsset(或其任何子类)并不简单。你真的只想这样做一次。关键是使用这个序列:

  1. 加载 AVAsset(例如,如果您从文件加载,则直接使用 AVURLAsset 或将其添加到 AVMutableComposition 并使用它)并保留对它的引用。在完成之前不要放手。加载它总是需要时间。
  2. 准备好播放后:使用您的资源实例化 AVPlayerItem,然后使用 AVPlayerItem 实例化 AVPlayer 并播放它。不要保留对 AVPlayerItem 的引用,AVPlayer 将保留对它的引用,并且您无论如何都不能与其他播放器重用它。
  3. 一旦播放完毕,立即销毁 AVPlayer...释放它,将其 var 设置为 nil,无论您需要做什么。 **
  4. 现在您可以录制了。 AVPlayer 不存在,所以 AVAudioRecorder 可以自由地做它的事情。
  5. 当您准备好再次玩时,使用您已经加载的资源重新实例化 AVPlayerItem AVP 播放器。再说一遍,这是微不足道的。资产已经加载,因此不应有延迟。

** 请注意,销毁 AVPlayer 可能不仅仅需要释放它并将其 var 设置为 nil。最有可能的是,您还添加了一个周期性时间观察器来跟踪播放进度。当你这样做时,你会收到一个你应该抓住的不透明物体。如果您不从播放器中删除此项目并释放它/将其设置为 nil,AVPlayer 将不会释放。 Apple 似乎故意创建了一个必须手动打破的保留周期。因此,在销毁 AVPlayer 之前,您需要(示例):

[_player removeTimeObserver:_playerObserver];
[_playerObserver release]; //Only if you're not using ARC
 _playerObserver = nil;

作为旁注,您可能还设置了 NSNotifications(我使用一个来确定播放器何时完成播放)...也不要忘记删除它们。

I've been having the same problem. I use AVPlayer to play compositions (previous recordings I've used AVAudioRecord for). However, I found that once I've used AVPlayer I could no longer use AVAudioRecorder. After some searching, I discovered that so long as AVPlayer is instantiated in memory and has been played at least once (which is usually what you do immediately after instantiating it) AVAudioRecorder will not record. However, once AVPlayer is dealloc'd, AVAudioRecorder is then free to record again. It appears that AVPlayer holds on to some kind of connection that AVAudioRecorder needs, and it's greedy...it won't let it go until you pry it from it's cold dead hands.

This is the solution I've found. Some people claim that instantiating AVPlayer takes too much time to keep breaking down and setting back up. However, this is not true. Instantiating AVPlayer is actually quite trivial. So also is instantiating AVPlayerItem. What isn't trivial is loading up AVAsset (or any of it's subclasses). You really only want to do that once. They key is to use this sequence:

  1. Load up AVAsset (for example, if you're loading from a file, use AVURLAsset directly or add it to a AVMutableComposition and use that) and keep a reference to it. Don't let it go until you're done with it. Loading it is what takes all the time.
  2. Once you're ready to play: instantiate AVPlayerItem with your asset, then AVPlayer with the AVPlayerItem and play it. Don't keep a reference to AVPlayerItem, AVPlayer will keep a reference to it and you can't reuse it with another player anyway.
  3. Once it's done playing, immediately destroy AVPlayer...release it, set its var to nil, whatever you need to do. **
  4. Now you can record. AVPlayer doesn't exist, so AVAudioRecorder is free to do its thing.
  5. When you're ready to play again, re-instantiate AVPlayerItem with the asset you've already loaded & AVPlayer. Again, this is trivial. The asset has already been loaded so there shouldn't be a delay.

** Note that destroying AVPlayer may take more than just releasing it and setting its var to nil. Most likely, you've also added a periodic time observer to keep track of the play progress. When you do this, you receive back an opaque object you're supposed to hold on to. If you don't remove this item from the player AND release it/set it to nil, AVPlayer will not dealloc. It appears that Apple creates an intentional retain cycle you must break manually. So before you destroy AVPlayer you need to (example):

[_player removeTimeObserver:_playerObserver];
[_playerObserver release]; //Only if you're not using ARC
 _playerObserver = nil;

As a side note, you may also have set up NSNotifications (I use one to determine when the player has completed playing)...don't forget to remove those as well.

往事随风而去 2024-10-30 18:40:26

如果您需要同时使用 AVPlayer 和 AVAudioRecorder,请执行以下操作:

  1. 将音频类别设置为“播放和录制”(如上所述或使用基于 C 的音频会话函数)
  2. 调用“播放”方法后必须调用“录制”方法有一些延迟。 (我设置了0.5秒)

如果你不提供这个,播放将开始,但录音不会开始。

If you need use AVPlayer and AVAudioRecorder at the same time do following:

  1. set audio category to "play and record" (as described above or with C-based Audio Session Function)
  2. "record" method must be invoked after invocation of "play" method with some delay. (I set 0.5 sec)

If you don't provide this, playback will start, but recording will not start.

过去的过去 2024-10-30 18:40:26

不应该是[AVAudioRecorder record];而不是play吗?

shouldn't it be [AVAudioRecorder record]; instead of play?

草莓酥 2024-10-30 18:40:26

我遇到了同样的问题:AVAudioRecorder 没有开始录音。
我的示例有点不同:我有一个基于选项卡栏的应用程序,在不同的视图中包含多个 AVAudioPlayer。为了便于举例,假设第一个加载的视图有 3 个 AVAudioPlayer,而第二个视图有一个 AVAudioPlayer 和一个 AVAudioRecorder。它们都是在viewDidLoad方法中发起的。

录音机在第二个视图中无法工作。当我按下录制按钮时,视图轻微晃动,并且录制没有开始。
奇怪的是,模拟器工作正常并且没有表现出相同的症状...(有人知道为什么吗?)

经过一些研究和阅读这篇文章,我意识到我没有将第一个视图中的玩家设置为零,所以我猜测它们仍在内存中,阻止录音机启动。一旦我在 viewDidDisappear 方法中将它们设置为 nil ,它就再次正常工作了。

这对我有帮助:

-(void)viewDidDisappear:(BOOL)animated {
    firstPlayer = nil;
    secondPlayer = nil;
    thirdPlayer = nil;
}

ViewDidUnload 没有帮助,因为切换视图时,视图以及类本身中的变量没有被卸载。

希望这对其他人也有用。

I've had the same issue: AVAudioRecorder did not start recording.
My example is a bit different: I have a tabbar based app with several AVAudioPlayers in the different views. For the sake of the example, lets say that the first loaded view has 3 AVAudioPlayers, while the second view has one AVAudioPlayer and one AVAudioRecorder. They are all initiated in the viewDidLoad method.

The recorder was not working in second view. When I hit my record button, the view slightly shaked and the recording did not begin.
Strangely, the simulator worked fine and did not show the same symptoms... (anyone has an idea why?)

After some research and reading this thread I have realized that I have not set the players in the first view to nil, so I guess they were still in the memory preventing the recorder to start. Once I have set them to nil in the viewDidDisappear method, it was working alright again.

here is what helped me:

-(void)viewDidDisappear:(BOOL)animated {
    firstPlayer = nil;
    secondPlayer = nil;
    thirdPlayer = nil;
}

ViewDidUnload did not help because the View, and therefore the variablbes in the class itself were not unloaded when switching views.

Hope this may be useful for others as well.

凉风有信 2024-10-30 18:40:26

@Aaron Hayman 的解释是准确的,但对我来说解决方案非常简单。只需实现播放器委托的 didFinishPlaying 方法并在那里释放播放器即可。

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    self.playerWord = nil;
}

@Aaron Hayman explanation is accurate but the solution for me was very simple. Just implement the didFinishPlaying method of the player delegate and release the player there.

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    self.playerWord = nil;
}
绳情 2024-10-30 18:40:26

当我开发一个播放音频文件和录制用户声音的应用程序时,我遇到了同样的问题。我尝试了上面的解决方案,例如 AVPlayer 实例的 deinit,但这没有帮助。就我而言,解决方案是在使用 AVAudioRecorder 之前停用并激活 AVAudioSession 实例。我使用了这样的函数:

func activateSession() {
    do {
        try session.setCategory(
            .playAndRecord,
            mode: .default,
            options: []
        )
    } catch _ {}
    do {
        try session.setActive(true, options: .notifyOthersOnDeactivation)
    } catch _ {}
}

func deactivateSession() {
    do {
        try session.setActive(false, options: .notifyOthersOnDeactivation)
    } catch {}
}

所以,用法是这样的:

func setupRecorder() throws {
    let recordingSettings = [
        AVFormatIDKey: kAudioFormatMPEG4AAC,
        AVSampleRateKey: 12000,
        AVNumberOfChannelsKey: 1,
        AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue] as [String : Any]
    let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let audioFilename = documentPath.appendingPathComponent("recording.m4a")

    deactivateSession()
    activateSession()

    do {
        audioRecorder = try AVAudioRecorder(url: audioFilename, settings: recordingSettings)
    } catch(let error) {}
    audioRecorder?.prepareToRecord()
}

When I was developing an app with playing audio files and recording user's voice I've encountered the same problem. I tried out solutions from above like deinit of AVPlayer instance, but that didn't help. In my case the solution was in deactivating and then activating an instance of AVAudioSession just before the use of AVAudioRecorder. I used functions like:

func activateSession() {
    do {
        try session.setCategory(
            .playAndRecord,
            mode: .default,
            options: []
        )
    } catch _ {}
    do {
        try session.setActive(true, options: .notifyOthersOnDeactivation)
    } catch _ {}
}

func deactivateSession() {
    do {
        try session.setActive(false, options: .notifyOthersOnDeactivation)
    } catch {}
}

So, the usage was like this:

func setupRecorder() throws {
    let recordingSettings = [
        AVFormatIDKey: kAudioFormatMPEG4AAC,
        AVSampleRateKey: 12000,
        AVNumberOfChannelsKey: 1,
        AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue] as [String : Any]
    let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let audioFilename = documentPath.appendingPathComponent("recording.m4a")

    deactivateSession()
    activateSession()

    do {
        audioRecorder = try AVAudioRecorder(url: audioFilename, settings: recordingSettings)
    } catch(let error) {}
    audioRecorder?.prepareToRecord()
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文