AVPlayer淡入

AVPlayer fadeIn

我一直在努力尝试为 AVPlayer 实现 fadeIn 方法。我什至尝试制作扩展,但我不知道如何将它附加到 AVPlayer。

我不知道为什么这不起作用。我可以看到音频播放器音量正在从零调整到最大音量的打印语句,但在函数退出之前我听不到任何音量,然后它达到最大音量,没有淡入。

我在游乐场工作:

import Cocoa
import AVFoundation

let url = URL(fileURLWithPath: "Sample.mp3")

func fadeIn(player: AVPlayer, fadeIn: Float) {
    let volumeInc = Float(1.0 / 10.0)
    let fadeInc = Float(fadeIn / 10.0)
    let sleepTime = useconds_t(fadeInc * 1000000)
    var seconds = Float(0.0)
    while seconds < fadeIn {
        usleep (sleepTime)
        print("gainInc (\(volumeInc)) + player.volume (\(player.volume)) = \(volumeInc + player.volume)")
        if (volumeInc + player.volume) > 1.0 {
            print("Breaking out of the while loop.")
            break
        } else {
            print("Incrementing the player.volume (\(player.volume)) by gainInc (\(volumeInc))")
            player.volume += volumeInc
            seconds += fadeInc
        }
    }
}

let player = AVPlayer(url: url)
player.seek(to: CMTimeMakeWithSeconds(45, preferredTimescale: 60000))
player.volume = 0
player.play()
fadeIn(player: player, fadeIn: 2)

AVPlayer 似乎被阻止了,因为即使我放弃方法调用并直接输入

let player = AVPlayer(url: url)
player.seek(to: CMTimeMakeWithSeconds(45, preferredTimescale: 60000))
player.volume = 0
player.play()
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1
usleep(200000)
player.volume += 0.1

该播放器仍被阻止。然后我更进一步尝试

let player = AVPlayer(url: url)
player.seek(to: CMTimeMakeWithSeconds(45, preferredTimescale: 60000))
player.volume = 1
player.play()
usleep(2000000)

而且玩家仍然被封锁。我还没有读过任何要求 AVPlayer 在它自己的线程中的内容,那么这种行为是否正确?我需要从这个兔子洞里爬出来再找一个下去吗?

编辑: 所以,我实现了答案,我认为我有那个中提琴时刻,因为我可以用播放计时器监视任何按键并使用嵌套计时器淡入淡出根据按键按下或淡出,同时跟踪播放时间。但是,在尝试进一步实现答案时,当我尝试在 playTimer 计时器内对 fadeItIn 进行计时时,我再次遇到了阻塞操作。

我基本上想创建一个应用程序,它的作用类似于广播电台扫描仪,可以逐步浏览我的媒体库并在超过 2 秒的时间内淡出一首歌曲并播放 10 秒(可能是 10 秒,但我使用 25用于测试),如果我喜欢它并想听更多,我可以单击“继续播放结束”按钮。但是,如果我不单击该按钮或 pause/stop/next 曲目按钮,播放器会以 2 秒淡出结束并继续播放我的媒体库中的下一首曲目。

更新代码:

import Cocoa
import AVFoundation
import PlaygroundSupport

let url = URL(fileURLWithPath: "Sample.mp3")
let startTime = 45
let fadeIn = 2
let fadeOut = 2
let playTime = 25
let player = AVPlayer(url: url)
let maxVolume:Float = 1.00
var toEnd = false
var pausePlayer = false
var nextTrack = false
var stopPlayer = false
var timePlayed = 0
var playerVolume:Float = 0.00
player.seek(to: CMTimeMakeWithSeconds(Float64(startTime), preferredTimescale: 60000))
player.volume = 0
player.play()
print("player maxVolume = \(maxVolume)")
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { playTimer in
    let currentTime = Int(player.currentTime().seconds-Double(startTime))
    if currentTime > timePlayed {
        timePlayed += 1
        print("Current play time = \(currentTime)")
    }
    if currentTime == 0 {
        Timer.scheduledTimer(withTimeInterval: Double(fadeIn/10), repeats: true) { fadeItIn in
            print("player.volume before fadeIn adjustment = \(player.volume)")
            if playerVolume < maxVolume {
                // Doing this to prevent volume from exceeding 1.00
                playerVolume += 0.05
                player.volume = playerVolume
                print("player.volume after fadeIn adjustment = \(player.volume)")
            }
            if playerVolume >= maxVolume {
                print("fadeIn volume has reached maximum volume at \(player.volume), invalidating faderItIn")
                fadeItIn.invalidate()
            }
        }
    }
    if currentTime >= playTime-fadeOut {
        playerVolume = player.volume
        Timer.scheduledTimer(withTimeInterval: Double(fadeOut/10), repeats: true) { fadeItOut in
            print("player.volume before fadeOut adjustment= \(player.volume)")
            if playerVolume > 0.00 {
                // Doing this to prevent the volume from going negative
                playerVolume -= 0.05
                player.volume = playerVolume
                print("player.volume after fadeOut adjustment = \(player.volume)")
            }
            if player.volume <= 0 {
                print("fadeOut volume has reached minimum volume at \(player.volume), invalidating fadeItOut")
                fadeItOut.invalidate()
            }
        }
        print("Pausing player")
        player.pause()
        print("Setting player item to nil")
        player.replaceCurrentItem(with: nil)
        print("Invalidating playTimer")
        playTimer.invalidate()
    } else if pausePlayer && player.timeControlStatus.rawValue == 1 {
        player.pause()
    } else if toEnd || nextTrack || stopPlayer && player.timeControlStatus.rawValue == 1 {
        playTimer.invalidate()
        if stopPlayer || nextTrack {
            player.replaceCurrentItem(with: nil)
        }
    }
}
if toEnd {
    Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { playTimer in
        let currentTime = Int(player.currentTime().seconds-Double(startTime))
        if currentTime > timePlayed {
            print("Play time: \(currentTime)")
            timePlayed += 1
        }
        if pausePlayer && player.rate > 0 {
            player.pause()
        } else if !pausePlayer && player.rate == 0 {
            player.play()
        }
        if stopPlayer || nextTrack {
            player.pause()
            player.replaceCurrentItem(with: nil)
            playTimer.invalidate()
        }
    }
}

AVPlayer 是在主线程上工作的 UI 组件,因此使用 usleep 会阻塞线程,这可能会导致实际应用程序崩溃。

要实现您的功能,您应该异步更改播放器的音量,例如在当前 运行 循环中使用 Timer

Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { timer in
    player.volume += 0.1
    if player.volume >= 1 {
        timer.invalidate()
    }
}