| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- import Foundation
- import AVFoundation
- import Combine
- /// Detects system environment issues before starting a recording.
- /// Checks background audio, media volume, and microphone permissions.
- @Observable
- final class RecordingEnvironmentDetector {
-
- // MARK: - Published Warnings
-
- var isOtherAudioPlaying: Bool = false
- var isVolumeTooHigh: Bool = false
- var micPermissionStatus: AVAudioApplication.recordPermission = .undetermined
-
- /// List of human-readable warnings based on current environment state.
- var activeWarnings: [String] = []
-
- init() {
- checkEnvironment()
-
- // Listen to volume changes or other audio notifications if necessary
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(handleAudioRouteChanged),
- name: AVAudioSession.routeChangeNotification,
- object: nil
- )
- }
-
- /// Runs environment checks and updates warnings.
- func checkEnvironment() {
- let session = AVAudioSession.sharedInstance()
-
- // 1. Check if other audio is playing in the background
- self.isOtherAudioPlaying = session.isOtherAudioPlaying
-
- // 2. Check if output volume is too high (above 70%)
- self.isVolumeTooHigh = session.outputVolume > 0.7
-
- // 3. Check microphone permission status
- self.micPermissionStatus = AVAudioApplication.shared.recordPermission
-
- // Compile warning strings
- var warnings: [String] = []
-
- if isOtherAudioPlaying {
- warnings.append("⚠️ 检测到后台有其他音频播放中,建议关闭以防混入录音。")
- }
-
- if isVolumeTooHigh {
- warnings.append("⚠️ 系统媒体音量过高 (%.0f%%),录音时建议降低音量。" .replacingOccurrences(of: "%.0f%%", with: String(format: "%.0f%%", session.outputVolume * 100)))
- }
-
- if micPermissionStatus == .denied {
- warnings.append("⚠️ 麦克风访问权限被禁用,请前往系统设置开启麦克风。")
- }
-
- self.activeWarnings = warnings
- }
-
- @objc private func handleAudioRouteChanged() {
- // Run checks on background thread to avoid blocking main loop, then dispatch updates
- DispatchQueue.main.async { [weak self] in
- self?.checkEnvironment()
- }
- }
- }
|