AVPlayer淡入

问题描述

我一直在与这个战斗,尝试为AVPlayer实现一个fadeIn方法。我什至尝试进行扩展,但是我不知道如何将其附加到AVPlayer。

我不知道为什么这行不通。我可以看到一些打印语句,说明audioPlayer的音量已从零调整为满音量,但是直到函数退出然后达到满音量且没有渐变输入时,我才听到任何音量。

我在操场上工作

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)
@H_404_8@

似乎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
@H_404_8@

播放器仍在被阻止。然后,我又走了一步,尝试了

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

播放器仍然被阻止。我还没有阅读任何要求AVPlayer进入其自己线程的内容,所以这种行为正确吗?我是否需要从这个兔子洞里爬出来找到另一个下山路?

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

我基本上是想创建一个类似于广播电台扫描仪的应用程序,以逐步浏览我的媒体库并在2秒的时间内淡入一首歌曲并播放10秒钟(大概10秒钟,但我使用25秒钟进行测试) ),如果我喜欢它并希望听到更多信息,可以单击“继续播放到结束”按钮。但是,如果我没有单击该按钮,也没有单击暂停/停止/下一个曲目按钮,则播放器将以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()
        }
    }
}
@H_404_8@

解决方法

AVPlayer是可在主线程上运行的UI组件,因此使用usleep可以阻塞该线程,并可能导致实际应用程序崩溃。

要实现您的功能,您应该在当前运行循环上以Timer异步更改播放器的音量:

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