Foundation — AVAudioPlayer

AVAudioPlayer 是 Apple 提供的一个高层次的 API,用于在 iOS 和 macOS 上进行 音频播放。它是一个简单、轻量的类,主要用于本地文件的音频播放。无论是 .mp3.wav,还是 .m4a 等音频文件,你都可以通过 AVAudioPlayer 进行播放。更多详细信息可以参考 Apple 的官方文档 AVAudioPlayer


1. 基本功能 #

AVAudioPlayer 提供了如下功能:

  1. 音频文件播放
    • 播放本地存储的音频文件。
    • 支持音乐格式如 .mp3, .wav, .m4a 等。
  2. 音量控制
    • 可调整音量大小。
  3. 播放控制
    • 开始、暂停、停止、快进、倒退等功能。
  4. 播放速率调整
    • 支持变速播放。
  5. 循环播放
    • 支持音频的无限循环。
  6. 回调监听
    • 提供播放完成等事件的监听支持。

2. 基本属性和方法 #

初始化音频播放器 #

  • 需要先提供音频文件的 URL,并通过 AVAudioPlayer 初始化播放器。
  • 通常的初始化方法:
    • AVAudioPlayer(contentsOf: URL):从文件 URL 初始化播放器。

主要方法 #

方法功能
play()开始播放音频文件。
pause()暂停播放音频。
stop()停止播放,并将进度重置为起始位置。
prepareToPlay()预加载音频到内存,减少开始播放的延迟。

主要属性 #

属性含义
volume控制音量,范围为 0.01.0
numberOfLoops设置循环次数,-1 代表无限循环。
duration音频文件的总时长(秒)。
currentTime当前播放位置(秒),可用于快进或快退。
isPlaying是否正在播放,返回布尔值。
enableRate是否启用速率调整功能。
rate播放速率,默认值是 1.0,表示正常速度。

3. 基础使用示例 #

1. 播放音频的基础代码 #

以下是一段使用 AVAudioPlayer 播放音频的基础代码。

import AVFoundation

class AudioPlayerExample {
    var audioPlayer: AVAudioPlayer?
    
    func playAudio() {
        // 获取音频文件的本地 URL
        guard let url = Bundle.main.url(forResource: "example", withExtension: "mp3") else {
            print("Audio file not found")
            return
        }
        
        do {
            // 初始化 AVAudioPlayer
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.volume = 0.5 // 设置音量为 50%
            audioPlayer?.numberOfLoops = 0 // 不循环
            audioPlayer?.prepareToPlay() // 准备播放
            audioPlayer?.play() // 开始播放
        } catch let error {
            print("Failed to initialize AVAudioPlayer: \(error.localizedDescription)")
        }
    }
}
  • 首先需要将音频文件添加到项目中,并确保它被正确导入到工程的 Bundle。
  • Bundle.main.url(forResource:withExtension:):用于获取音频的本地路径。
  • prepareToPlay():减少播放延迟。
  • play():开始播放音频文件。

2. 创建 AVAudioPlayer 实例 #

首先,你需要创建一个 AVAudioPlayer 的实例,并初始化它。通常,你会在 viewDidLoad 或其他适当的位置进行初始化。

class AudioPlayerExample {
    var audioPlayer: AVAudioPlayer?

    func setupAudioPlayer() {
        guard let url = Bundle.main.url(forResource: "sound", withExtension: "mp3") else {
            print("音频文件未找到")
            return
        }

        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.prepareToPlay() // 准备播放
        } catch {
            print("初始化音频播放器失败: \(error)")
        }
    }
}

3. 播放音频 #

一旦你设置好 AVAudioPlayer,就可以调用 play() 方法来播放音频:

func playAudio() {
    audioPlayer?.play()
}

4. 暂停和停止音频 #

你可以使用 pause() 方法来暂停音频,使用 stop() 方法来停止音频播放:

func pauseAudio() {
    audioPlayer?.pause()
}

func stopAudio() {
    audioPlayer?.stop()
    audioPlayer?.currentTime = 0 // 重置播放时间
}

5. 示例:完整的 AVAudioPlayer 使用 #

以下是一个完整的示例,展示如何使用 AVAudioPlayer 播放音频文件:

import UIKit
import AVFoundation

class ViewController: UIViewController {
    var audioPlayer: AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupAudioPlayer()
    }

    func setupAudioPlayer() {
        guard let url = Bundle.main.url(forResource: "sound", withExtension: "mp3") else {
            print("音频文件未找到")
            return
        }

        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.prepareToPlay()
        } catch {
            print("初始化音频播放器失败: \(error)")
        }
    }

    @IBAction func playButtonTapped(_ sender: UIButton) {
        playAudio()
    }

    @IBAction func pauseButtonTapped(_ sender: UIButton) {
        pauseAudio()
    }

    @IBAction func stopButtonTapped(_ sender: UIButton) {
        stopAudio()
    }

    func playAudio() {
        audioPlayer?.play()
    }

    func pauseAudio() {
        audioPlayer?.pause()
    }

    func stopAudio() {
        audioPlayer?.stop()
        audioPlayer?.currentTime = 0
    }
}

4. 关键功能扩展 #

以下示例介绍一些 AVAudioPlayer 的关键功能及其使用方式。


4.1 设置音量 #

通过 volume 属性设置音量大小,范围为 0.0(静音)到 1.0(最大音量)

audioPlayer?.volume = 0.8 // 将音量设置为 80%

4.2 调整播放速率 (Rate) #

通过 rate 属性调整播放速度(变速播放):

  • 默认速率为 1.0
  • 值 < 1.0 表示减速播放。
  • 值 > 1.0 表示加速播放。
audioPlayer?.enableRate = true // 启用速率调整
audioPlayer?.rate = 1.5        // 设置为 1.5 倍速播放

4.3 设置循环播放 #

通过调整 numberOfLoops 属性控制音频的播放次数:

  • numberOfLoops = 0:音频只播放一次。
  • numberOfLoops = -1:音频无限循环。
audioPlayer?.numberOfLoops = -1 // 无限循环播放

4.4 跳转到指定位置 #

通过 currentTime 属性调整播放进度:

  • 设置 currentTime 可以快进或倒退。
audioPlayer?.currentTime = 30.0 // 跳转到 30 秒位置

4.5 检测播放状态 #

通过 isPlaying 属性检查播放器是否正在播放:

if audioPlayer?.isPlaying == true {
    print("Audio is currently playing")
}


5. 添加事件监听 #

AVAudioPlayer 实现了 AVAudioPlayerDelegate 协议,可以监听播放完成及播放错误等关键事件。

示例:监听事件 #

import AVFoundation

class AudioPlayerExample: NSObject, AVAudioPlayerDelegate {
    var audioPlayer: AVAudioPlayer?
    
    func playAudio() {
        guard let url = Bundle.main.url(forResource: "example", withExtension: "mp3") else { return }
        do {
            // 初始化并设置代理
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.delegate = self
            audioPlayer?.play()
        } catch {
            print("Error initializing audio player")
        }
    }
    
    // MARK: - AVAudioPlayerDelegate Methods
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        print("Playback finished successfully: \(flag)")
    }
    
    func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
        print("Audio player decoding error: \(error?.localizedDescription ?? "Unknown error")")
    }
}
  • audioPlayerDidFinishPlaying(_:successfully:):当音频播放完成时被触发。
  • audioPlayerDecodeErrorDidOccur(_:error:):如果解码音频文件时发生错误,则触发该回调。

以下是两个场景的示例,一个是不需要设置代理的情况,另一个是需要设置代理的情况。

场景 1: 不需要设置代理 #

在这个场景中,我们只需要播放音频,而不关心播放的状态或事件。

import AVFoundation

class SimpleAudioPlayer {
    private var audioPlayer: AVAudioPlayer?

    func playSound(url: URL) {
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.prepareToPlay()
            audioPlayer?.play() // 直接播放,不需要设置代理
        } catch {
            print("Error initializing audio player: \(error)")
        }
    }
}

说明: 在这个例子中,我们只需要播放音频文件,不需要处理播放完成或播放中断等事件,因此不需要设置代理。


场景 2: 需要设置代理 #

在这个场景中,我们需要处理音频播放完成的事件,以便更新 UI 或执行其他操作。

import AVFoundation

class AudioPlayer: NSObject, AVAudioPlayerDelegate {
    private var audioPlayer: AVAudioPlayer?

    func playSound(url: URL) {
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.delegate = self // 设置代理
            audioPlayer?.prepareToPlay()
            audioPlayer?.play()
        } catch {
            print("Error initializing audio player: \(error)")
        }
    }

    // AVAudioPlayerDelegate 方法
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        if flag {
            print("Audio finished playing successfully.")
            // 在这里更新 UI 或执行其他操作
        } else {
            print("Audio did not finish playing successfully.")
        }
    }
}

说明: 在这个例子中,我们设置了 audioPlayer 的代理为 self,并实现了 audioPlayerDidFinishPlaying(_:successfully:) 方法。当音频播放完成时,这个方法会被调用,我们可以在这里更新 UI 或执行其他操作。

总结 #

  • 不需要设置代理: 当你只需要播放音频,而不关心播放状态时。
  • 需要设置代理: 当你需要处理音频播放的状态变化(如播放完成、播放中断等)时。

6. 常见扩展功能 #

6.1 使用远程音频文件 #

AVAudioPlayer 不支持直接播放远程音频,需要先将其下载到本地后再播放。如果需要直接播放流式音频,使用 AVPlayer 会更好。


6.2 淡入/淡出音量 #

通过调整 volume 属性和定时器,可以实现淡入/淡出的效果。

示例:播放时淡入效果 #

func fadeInAudio() {
    audioPlayer?.volume = 0.0
    audioPlayer?.play()
    
    Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
        if self.audioPlayer?.volume ?? 0 < 1.0 {
            self.audioPlayer?.volume += 0.1
        } else {
            timer.invalidate() // 停止定时器
        }
    }
}

7. 注意事项 #

  1. 本地文件:

    • AVAudioPlayer 仅支持播放本地音频文件,不能直接播放远程音频 URL。
    • 如果需要远程播放,可以先下载文件或使用 AVPlayer
  2. 性能注意:

    • 对于开发音频播放 app,例如多音轨混音,推荐使用 AVAudioEngine,它提供更大的灵活性和实时处理能力。
  3. 错误处理:

    • 初始化播放器时可能会抛出错误,需要用 do-catch 捕获并处理。

总结 #

AVAudioPlayer 是一个轻量的音频播放工具类,适合用来播放简单的音频文件,例如添加背景音乐或音效。功能相对简单,但足够满足大部分本地音频播放需求。

推荐使用场景: #

  1. 播放本地存储的音频文件。
  2. 构建简单的音频播放器应用。
  3. 播放单一音轨的音频。

不适用场景: #

  • 播放远程音频流(应使用 AVPlayer)。
  • 复杂的实时音效处理(应使用 AVAudioEngine)。
本文共 2618 字,上次修改于 Jan 1, 2025