You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中实现录音与设备媒体音频同时播放的问题咨询

在SwiftUI iPad应用中实现录音与背景音频共存

我刚好处理过类似的需求——在录音时让设备上的背景音乐/视频音频继续播放,类似Snap的带音乐短视频录制场景。你用AVAudioSession.Category.playAndRecord配合.mixWithOthers的方向是对的,但在iOS 15.5上,还需要补充几个关键配置才能让它正常工作。

核心配置要点

  1. 完整的会话选项组合
    除了.mixWithOthers,建议添加.defaultToSpeaker选项,确保录音时音频从扬声器输出(默认情况下playAndRecord会使用听筒,可能导致背景音频被压低或中断)。另外,激活会话时使用.notifyOthersOnDeactivation,能让你的应用结束录音后,其他音频会话自动恢复正常。

  2. 正确的权限申请
    别忘了在Info.plist中添加NSMicrophoneUsageDescription,否则录音权限会被拒绝,间接导致音频会话配置失效。

完整代码示例

下面是一个可直接使用的音频录音管理器类,配合SwiftUI视图实现功能:

import AVFoundation
import SwiftUI

class AudioRecorderManager: NSObject, ObservableObject {
    private var audioRecorder: AVAudioRecorder?
    
    /// 配置音频会话并激活
    func setupAudioSession() {
        let session = AVAudioSession.sharedInstance()
        do {
            // 使用playAndRecord分类,搭配mixWithOthers和defaultToSpeaker选项
            try session.setCategory(.playAndRecord,
                                    mode: .default,
                                    options: [.mixWithOthers, .defaultToSpeaker])
            // 激活会话时通知其他音频应用
            try session.setActive(true, options: .notifyOthersOnDeactivation)
        } catch {
            print("会话配置失败:\(error.localizedDescription)")
        }
    }
    
    /// 开始录音
    func startRecording() {
        // 生成录音文件存储路径
        let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let audioURL = docsDir.appendingPathComponent("background_recording.m4a")
        
        // 录音设置(使用AAC编码,保证音质和兼容性)
        let recordingSettings: [String: Any] = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 44100.0,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]
        
        do {
            audioRecorder = try AVAudioRecorder(url: audioURL, settings: recordingSettings)
            audioRecorder?.record()
            print("开始录音,文件路径:\(audioURL.path)")
        } catch {
            print("启动录音失败:\(error.localizedDescription)")
        }
    }
    
    /// 停止录音
    func stopRecording() {
        audioRecorder?.stop()
        audioRecorder = nil
        let session = AVAudioSession.sharedInstance()
        do {
            try session.setActive(false, options: .notifyOthersOnDeactivation)
        } catch {
            print("停用会话失败:\(error.localizedDescription)")
        }
        print("录音已停止")
    }
}

// SwiftUI视图示例
struct AudioRecordingView: View {
    @StateObject private var recorderManager = AudioRecorderManager()
    
    var body: some View {
        VStack(spacing: 20) {
            Button("开始录音(保留背景音频)") {
                recorderManager.setupAudioSession()
                recorderManager.startRecording()
            }
            .buttonStyle(.borderedProminent)
            
            Button("停止录音") {
                recorderManager.stopRecording()
            }
            .buttonStyle(.bordered)
        }
        .padding()
        .onAppear {
            // 提前申请录音权限
            AVAudioSession.sharedInstance().requestRecordPermission { granted in
                if granted {
                    print("录音权限已获取")
                } else {
                    print("录音权限被拒绝,无法正常录音")
                }
            }
        }
    }
}

额外优化建议

  • 如果你的场景更偏向“视频录制+背景音频”,可以把会话模式改成.videoRecording,这个模式是苹果专门为视频录制场景优化的,能更好地平衡录音和背景音频的播放效果:
    try session.setCategory(.playAndRecord,
                            mode: .videoRecording,
                            options: [.mixWithOthers, .defaultToSpeaker])
    
  • 测试时先启动第三方音乐/视频应用播放音频,再打开你的应用点击录音按钮,验证背景音频是否继续播放。

内容的提问来源于stack exchange,提问作者Amélie Mouillac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:59:07