2

我知道这个问题在 Stack Overflow 上到处都是,但其中大多数都是旧的,与我在这里要问的问题无关。

所以我有一个数组AVPlayerItems和一个AVQueuePlayer. 起初我将 AVQueuePlayer 设置为播放数组项:

func mediaPicker(mediaPicker: MPMediaPickerController!, didPickMediaItems mediaItemCollection: MPMediaItemCollection!) {

    mediaItems = mediaItemCollection.items

    for thisItem in mediaItems as [MPMediaItem] {

        var itemUrl = thisItem.valueForProperty(MPMediaItemPropertyAssetURL) as? NSURL
        var playerItem = AVPlayerItem(URL: itemUrl)
        mediaArray.append(playerItem)           

    }

    updateMetadata()

    audioPlayer = AVQueuePlayer(items: mediaArray)


    self.dismissViewControllerAnimated(true, completion: nil)

}

但是,例如,当用户添加一个新项目或删除一个项目时,我尝试更新播放器(与我最初设置它的方式相同),但它给了我错误。我想知道是否有任何解决方法或任何解决方案。这是用户删除歌曲的方式:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == UITableViewCellEditingStyle.Delete{
            mediaArray.removeAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
            audioPlayer = AVQueuePlayer(items: mediaArray) //here gives the error
        }
    }

我正在为此自杀,所以,如果有人可以帮助我,我将不胜感激。

4

6 回答 6

4

问题是当您使用此行更新项目数组时(在 tableView:commitEditingStyle:forRowAtIndexPath:) 中,您正在创建一个新的播放器对象,

audioPlayer = AVQueuePlayer(items: mediaArray)

执行此操作时,播放器项目似乎仍与原始播放器相关联。您应该能够删除该行,使其正常工作。从 mediaArray 插入或删除项目应该足以满足您的需求;您无需创建新播放器。

于 2015-06-05T15:19:19.570 回答
2

苹果文档

添加项目之前:

canInsertItem(_:afterItem:)

返回一个布尔值,指示是否可以将给定的玩家项目插入到玩家的队列中。

func canInsertItem(_ item: AVPlayerItem!, afterItem afterItem: AVPlayerItem!) -> Bool

添加项目:

insertItem(_:afterItem:)

将给定的播放器项目放置在队列中的指定项目之后。

 func insertItem(_ item: AVPlayerItem!, afterItem afterItem: AVPlayerItem!)

删除项目:

removeItem(_:)

从队列中移除给定的玩家项目。

func removeItem(_ item: AVPlayerItem!)

于 2015-06-05T03:11:12.033 回答
2

我解决这个问题的方法是我AVAsset在数组中保留对对象的引用,然后将其mapped 到[AVPlayerItem]AVQUeuePlayerinit 接受的类型)。

详细地说,我们需要制作一个可以暂停的录音机(github上的代码AVQueuePlayer),所以我使用了一个,但遇到了与 OP 相同的问题,唯一干净的解决方案是用一个新数组重新创建这个播放器对象.

Swift 4.1中的相关代码:

class RecordViewController: UIViewController {

    var audioRecorder: AVAudioRecorder?

    var audioChunks = [AVURLAsset]()
    var queuePlayer:  AVQueuePlayer?

// irrelevant code omitted

    func stopRecorder() {
        self.audioRecorder?.stop()
        let assetURL  = self.audioRecorder!.url

        self.audioRecorder = nil

        let asset = AVURLAsset(url: assetURL)
        self.audioChunks.append(asset)

        let assetKeys = ["playable"]
        let playerItems = self.audioChunks.map {
            AVPlayerItem(asset: $0, automaticallyLoadedAssetKeys: assetKeys)
        }

        self.queuePlayer = AVQueuePlayer(items: playerItems)
        self.queuePlayer?.actionAtItemEnd = .advance
    }

    func startPlayer() {
        self.queuePlayer?.play()
    }

    func stopPlayer() {
        self.queuePlayer?.pause()
        self.queuePlayer = nil
    }
}

(最后,AVAssetExportSession用于将音频块重新拼接在一起,因此最终将 s 存储AVAssetAVPlayerItems 中更为有益。)

于 2018-04-20T00:12:41.920 回答
1

使用此代码为我解决了这个问题:

player?.pause()                     
let playerItem = AVPlayerItem(asset: myAsset) 
player = nil 
player = AVPlayer()
player?.replaceCurrentItem(with: playerItem)

代替:

player?.pause()                     
player = nil 
player = AVPlayer()
player?.replaceCurrentItem(with: availablePlayerItem) 
//availablePlayerItem is a playerItem which has been created before and played once with this AVPlayer

注意:在这两个代码中,“玩家”是我班级中的一个全局变量,即:

var player : AVPlayer? = 无

于 2020-02-09T13:04:25.900 回答
0

我最初在一个单元格内初始化了一个 AVPlayerItem 并将其添加到一个 AVPlayer(也在单元格内)。后来我提出了一个新的 vc 并将同一个单元格的 AVPlayerItem 传递给新 vc 内的另一个 AVPlayer 并崩溃了。为了解决这个问题,我刚刚使用.copy() as? AVPlayerItem. 副本为新副本提供了与原始副本不同的内存地址。

细胞:

var cellPlayer: AVPlayer?
var cellsPlayerItem: AVPlayerItem?

cellsPlayerItem = AVPlayerItem(asset: AVAsset(url: url)) // cellsPlayerItem's memory address 0x1111111
cellPlayer = AVPlayer(playerItem: cellsPlayerItem!)

介绍了vc:

var vcPlayer: AVPlayer?

let playerItemCopy = cellsPlayerItem.copy() as? AVPlayerItem // playerItemCopy's memory address 0x2222222
let vcPlayer = AVPlayer(playerItem: playerItemCopy)
于 2020-06-08T12:09:12.253 回答
0

需要检查播放器项目是否可以插入播放器的队列。然后根据以下条件添加、删除或替换播放器项目:

if player.canInsert(playerItem, after: nil) == true {

            player = AVQueuePlayer(playerItem: playerItem)

        } else {

            player.remove(self.playerItem)

            player.replaceCurrentItem(with: playerItem)
}
于 2020-01-11T10:04:30.710 回答