declare enum AudioPermissionErrorType { NO_USER_INTERACTION_ERROR = "NoUserInteractionError", AUTOPLAY_BLOCKED = "AutoplayBlocked", AUTOPLAY_UNKNOWN_ERROR = "AutoplayUnknownError", SECURE_CONTEXT_ERROR = "SecureContextError", PERMISSION_DENIED_PERMANENTLY = "PermissionDeniedPermanently", NOT_ALLOWED_ERROR = "NotAllowedError", MEDIA_DEVICES_API_UNAVAILABLE = "MediaDevicesApiUnavailable", NOT_FOUND_ERROR = "NotFoundError", NOT_READABLE_ERROR = "NotReadableError", OVERCONSTRAINED_ERROR = "OverconstrainedError", SECURITY_ERROR = "SecurityError", MICROPHONE_UNKNOWN_ERROR = "MicrophoneUnknownError", MICROPHONE_TIMEOUT_ERROR = "MicrophoneTimeoutError" } declare class AudioPermissionError extends Error { name: AudioPermissionErrorType; private constructor(); static create(name: AudioPermissionErrorType, message?: string): AudioPermissionError; } /** * 音频播放权限管理类 * * 根据MDN文档,音频播放权限需要满足以下条件之一: * 1. 音频被静音或音量为0 * 2. 用户已与网站产生交互(点击、触摸、按键等) * 3. 网站已被加入自动播放白名单 * 4. 通过Permissions Policy授权 * * 跨平台实现策略: * - PC端:预检测AudioContext状态,如果suspended则监听用户交互 * - iOS Safari:必须在用户交互事件的调用栈中调用resume(),需要50ms延迟确保状态变更 * - Android:直接在用户交互后检测AudioContext状态 * * 自动播放策略限制: * - Chrome 66+:需要用户交互或MEI(Media Engagement Index)足够高 * - Safari:严格要求用户交互,AudioContext创建时默认为suspended状态 * - Firefox:相对宽松,但仍会阻止明显的自动播放行为 * * * * 实现原理: * PC: * 1.在PC端首先预检测AudioContext状态: * 如果状态是 “running” 状态则可以播放音频, * 如果状态不是 “running” 状态则需要监听用户交互事件, * 2.用户交互事件触发后,再检测AudioContext状态: * 如果状态是 “running” 状态则可以播放音频, * 如果状态不是 “running” 状态则抛出异常。 * * IOS: * 1.用户交互事件触发后,再检测AudioContext状态: * 如果状态是 “suspended” 则需要调用 resume 方法,并且需要延迟 50ms, * 如果状态不是 “suspended” 状态进行下一步判断, * 2.获取AudioContext状态: * 如果状态是 “running” 状态则可以播放音频, * 如果状态不是 “running” 状态则抛出异常。 * * Android: * 1.用户交互事件触发后,再检测AudioContext状态: * 如果状态是 “running” 状态则可以播放音频, * 如果状态不是 “running” 状态则抛出异常。 */ declare class AudioPlaybackPermission { private userInteracted; private executeContext; constructor(); /** * 初始化播放权限检测 */ private initPlaybackPermission; /** * 检测初始AudioContext状态(仅PC平台) */ private checkInitialAudioContextState; /** * 设置用户交互监听器 */ private setupUserInteractionListeners; /** * 请求播放权限 * 根据Web Audio API最佳实践实现 */ requestPlaybackPermission(): Promise; /** * 执行上下文设置 * @param context 执行上下文 */ setExecuteContext(context: AudioPermission): void; } /** * 麦克风权限管理类 * * 根据MDN文档,getUserMedia需要满足: * 1. 安全上下文(HTTPS) * 2. 用户明确授权 * 3. 顶级文档上下文或通过Permissions Policy授权的iframe * * * 权限状态说明: * - granted: 用户已授权,可直接访问麦克风 * - denied: 用户已拒绝,需要用户手动在浏览器设置中重新开启 * - prompt: 首次访问,会弹出授权对话框 * * * 平台差异: * - 桌面端:通过浏览器原生授权对话框处理 * - iOS Safari:权限被拒绝后,需要用户在系统设置中重新开启 * - Android Chrome:权限处理与桌面端类似,但某些版本可能有缓存问题 * * * 注意事项: * 1. 浏览器会永久缓存用户的权限决定 * 2. 在非HTTPS环境下(除localhost外)会直接失败 * 3. 某些浏览器在隐私模式下可能有不同行为 * 4. iframe中使用需要正确配置Permissions Policy * * * 实现原理: * - PC平台: * 1. 通过授权弹框申请权限: * 如果用户拒绝了权限,会抛出异常 * 如果用户点击了允许,会返回成功 * 2.第二次申请权限,会根据用户第一次申请权限的结果: * 如果用户第一次申请权限失败,会抛出异常 * 如果用户第一次申请权限成功,会返回成功 * - 移动端: * 1. 通过授权弹框申请权限: * 如果用户拒绝了权限,会抛出异常 * 如果用户点击了允许,会返回成功 * 2.第二次申请权限,会根据用户第一次申请权限的结果: * 如果用户第一次申请权限失败,会抛出异常 * 如果用户第一次申请权限成功,会返回成功 * * iOS平台: * 1. 通过授权弹框申请权限: * 如果用户拒绝了权限,会抛出异常 * 如果用户点击了允许,会返回成功 * 2.第二次申请权限,会根据用户第一次申请权限的结果: * 如果用户第一次申请权限失败,会抛出异常 * 如果用户第一次申请权限成功,会返回成功 * * */ declare class MicrophonePermission { private microphonePermissionGranted; private permissionDeniedPermanently; /** * 检查是否在安全上下文中 */ private isSecureContext; /** * 带超时的getUserMedia调用 * @param constraints - 媒体约束 * @param timeoutMs - 超时时间(毫秒) * @returns Promise */ private getUserMediaWithTimeout; /** * 请求麦克风权限 * 根据MediaDevices.getUserMedia规范实现 */ requestMicrophonePermission(): Promise; } /** * 统一的音频权限管理类 */ declare class AudioPermission { playbackPermission: AudioPlaybackPermission; microphonePermission: MicrophonePermission; constructor(); /** * 请求音频播放权限 */ requestPlaybackPermission(): Promise; /** * 请求麦克风权限 */ requestMicrophonePermission(): Promise; } /** * 创建或获取音频权限管理实例 */ declare function createAudioPermission(): AudioPermission; export default createAudioPermission; export { AudioPermission, AudioPermissionError, AudioPermissionErrorType, AudioPlaybackPermission, MicrophonePermission };