- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含多个单元格 (FeedCell
) 的 UICollectionView
。这些单元格还可以包含一个 UICollectionView
,它也可以有多个单元格,最多五个 (MediaSliderCell
)。基本上,设置与 Instagram 相同:您有一个帖子,一个帖子可以有多个图像或视频。
我现在面临的问题是,有时错误的视频会显示在错误的单元格中。当视频还没有播放时,我使用 imageView 来显示一个占位符,当视频开始播放时这个占位符是隐藏的(点击播放按钮)。
当我不播放视频时,我认为一切正常,但是当我播放视频时,问题就出现了。单元格切换,这意味着 MediaSliderCell indexPath.item
5 的视频显示在 MediaSLiderCell indexPath.item
2 中,例如。
起初,我认为问题出在细胞中,细胞没有得到很好的重复使用,但这也意味着照片可能会被调换,但这种情况从未发生过。所以我觉得问题出在我的 AVPlayer 中,它使用了错误的引用或错误的 URL。让我演示一下我的代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mediaSliderCell", for: indexPath) as! MediaSliderCell
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
if(HomeControllerID.userFeed.userFeed[feedCellID!].userMedia!.count > 0) {
if(HomeControllerID.userFeed.userFeed[feedCellID!].userMedia![indexPath.item].mediaType == .photo) {
let mediaURL = URL(string: "https://myfileserver.com/media/\(HomeControllerID.userFeed.userFeed[feedCellID!].feedID!)/\(HomeControllerID.userFeed.userFeed[feedCellID!].userMedia![indexPath.item].mediaURL)")
cell.photoView.kf.setImage(with: mediaURL, options: [.targetCache(mediaCache)])
cell.photoView.isHidden = false
cell.videoView.isHidden = true
} else if(HomeControllerID.userFeed.userFeed[feedCellID!].userMedia![indexPath.item].mediaType == .video) {
let mediaThumbURL = URL(string: "https://myfileserver.com/media/\(HomeControllerID.userFeed.userFeed[feedCellID!].feedID!)/\(HomeControllerID.userFeed.userFeed[feedCellID!].userMedia![indexPath.item].mediaThumbURL!)")
let mediaURL = URL(string: "https://myfileserver.com/media/\(HomeControllerID.userFeed.userFeed[feedCellID!].feedID!)/\(HomeControllerID.userFeed.userFeed[feedCellID!].userMedia![indexPath.item].mediaURL)")!
cell.videoView.placeholderView.kf.setImage(with: mediaThumbURL, options: [.targetCache(mediaCache)])
cell.videoView.mediaURL = mediaURL
cell.photoView.isHidden = true
cell.videoView.isHidden = false
}
}
return cell
}
MediaSLiderCell
是一些非常基本的 UICollectionViewCell
东西:
class MediaSliderCell: UICollectionViewCell {
override func prepareForReuse() {
super.prepareForReuse()
photoView.isHidden = false
videoView.isHidden = true
videoView.mediaURL = nil
videoView.placeholderView.kf.cancelDownloadTask()
videoView.placeholderView.image = UIImage()
photoView.image = UIImage()
}
var photoView: UIImageView = {
let photoView = UIImageView()
photoView.translatesAutoresizingMaskIntoConstraints = false
photoView.backgroundColor = .black
photoView.isHidden = true
return photoView
}()
var videoView: VideoView = {
let videoView = VideoView()
videoView.translatesAutoresizingMaskIntoConstraints = false
videoView.backgroundColor = .black
return videoView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
func setupViews() {
addSubview(photoView)
addSubview(videoView)
photoView.topAnchor.constraint(equalTo: topAnchor).isActive = true
photoView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
photoView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
photoView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
videoView.topAnchor.constraint(equalTo: topAnchor).isActive = true
videoView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
videoView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
videoView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我认为以上都可以。但是,对于 VideoView,我使用了一个自定义的 UIView
,我在其中设置了一个占位符 (UIImageView
)。下面有很多代码,但大多数是控件和用户界面的东西。重要的是,我使用了两个库:Cache和 CachingPlayerItem .这是为了避免一遍又一遍地下载相同的视频,所以当在缓存中找不到视频时,我下载该项目,当视频下载后,我将其保存在缓存中以备后用。我想一切都说得通。我觉得问题出在某个地方,或者在 AVPlayer 本身。看一下代码:
class VideoView: UIView, CachingPlayerItemDelegate {
var playerItem: CachingPlayerItem?
func playerItem(_ playerItem: CachingPlayerItem, didFinishDownloadingData data: Data) {
// A track is downloaded. Saving it to the cache asynchronously.
print("Saving video to cache on device")
storage?.async.setObject(data, forKey: mediaURL.absoluteString, completion: { _ in} )
}
var playerLooper: NSObject?
var playerLayer: AVPlayerLayer!
var queuePlayer: AVQueuePlayer?
var mediaURL: URL!
var placeholderView: UIImageView = {
let placeholderView = UIImageView()
placeholderView.translatesAutoresizingMaskIntoConstraints = false
placeholderView.backgroundColor = .black
return placeholderView
}()
var playerView: UIView = {
let playerView = UIView()
playerView.translatesAutoresizingMaskIntoConstraints = false
playerView.backgroundColor = .clear
playerView.isHidden = true
return playerView
}()
var playButton: UIImageView = {
let playButton = UIImageView()
playButton.image = UIImage(named: "playButton")
playButton.translatesAutoresizingMaskIntoConstraints = false
playButton.isUserInteractionEnabled = true
playButton.backgroundColor = .clear
return playButton
}()
var pauseButton: UIImageView = {
let pauseButton = UIImageView()
pauseButton.image = UIImage(named: "pauseButton")
pauseButton.translatesAutoresizingMaskIntoConstraints = false
pauseButton.backgroundColor = .clear
pauseButton.isUserInteractionEnabled = true
pauseButton.alpha = 0
return pauseButton
}()
var volumeOnButton: UIImageView = {
let volumeOnButton = UIImageView()
volumeOnButton.image = UIImage(named: "volumeOn")
volumeOnButton.translatesAutoresizingMaskIntoConstraints = false
volumeOnButton.backgroundColor = .clear
volumeOnButton.isUserInteractionEnabled = true
volumeOnButton.alpha = 0
return volumeOnButton
}()
var volumeOffButton: UIImageView = {
let volumeOffButton = UIImageView()
volumeOffButton.image = UIImage(named: "volumeOff")
volumeOffButton.translatesAutoresizingMaskIntoConstraints = false
volumeOffButton.backgroundColor = .clear
volumeOffButton.isUserInteractionEnabled = true
volumeOffButton.alpha = 0
return volumeOffButton
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.setupViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setupViews()
}
func setupViews() {
addSubview(placeholderView)
placeholderView.topAnchor.constraint(equalTo: topAnchor).isActive = true
placeholderView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
placeholderView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
placeholderView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
addSubview(playerView)
playerView.topAnchor.constraint(equalTo: topAnchor).isActive = true
playerView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
playerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
playerView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
let tapView = UITapGestureRecognizer(target: self, action: #selector(showControls))
playerView.addGestureRecognizer(tapView)
addSubview(playButton)
playButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
playButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
playButton.heightAnchor.constraint(equalToConstant: profilePicWidth * 2).isActive = true
playButton.widthAnchor.constraint(equalToConstant: profilePicWidth * 2).isActive = true
let tapPlayButton = UITapGestureRecognizer(target: self, action: #selector(playVideo))
playButton.addGestureRecognizer(tapPlayButton)
addSubview(pauseButton)
pauseButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
pauseButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
pauseButton.heightAnchor.constraint(equalToConstant: profilePicWidth * 2).isActive = true
pauseButton.widthAnchor.constraint(equalToConstant: profilePicWidth * 2).isActive = true
let tapPauseButton = UITapGestureRecognizer(target: self, action: #selector(pauseVideo))
pauseButton.addGestureRecognizer(tapPauseButton)
addSubview(volumeOnButton)
volumeOnButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -(normalSpacing + 2)).isActive = true
volumeOnButton.topAnchor.constraint(equalTo: topAnchor, constant: normalSpacing + 2).isActive = true
volumeOnButton.heightAnchor.constraint(equalToConstant: 32).isActive = true
volumeOnButton.widthAnchor.constraint(equalToConstant: 32).isActive = true
let tapVolumeOnButton = UITapGestureRecognizer(target: self, action: #selector(volumeAction))
volumeOnButton.addGestureRecognizer(tapVolumeOnButton)
addSubview(volumeOffButton)
volumeOffButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -(normalSpacing + 2)).isActive = true
volumeOffButton.topAnchor.constraint(equalTo: topAnchor, constant: normalSpacing + 2).isActive = true
volumeOffButton.heightAnchor.constraint(equalToConstant: 32).isActive = true
volumeOffButton.widthAnchor.constraint(equalToConstant: 32).isActive = true
let tapVolumeOffButton = UITapGestureRecognizer(target: self, action: #selector(volumeAction))
volumeOffButton.addGestureRecognizer(tapVolumeOffButton)
}
@objc func volumeAction() {
buttonTimer?.invalidate()
volumeTimer?.invalidate()
if UserDefaults.exists(key: "volumeOn") {
if(UserDefaults.standard.bool(forKey: "volumeOn") == false) {
self.queuePlayer?.isMuted = false
UserDefaults.standard.set(true, forKey: "volumeOn")
self.volumeOnButton.alpha = 1
self.volumeOffButton.alpha = 0
} else {
self.queuePlayer?.isMuted = true
UserDefaults.standard.set(false, forKey: "volumeOn")
self.volumeOnButton.alpha = 0
self.volumeOffButton.alpha = 1
}
} else {
self.queuePlayer?.isMuted = false
UserDefaults.standard.set(true, forKey: "volumeOn")
self.volumeOnButton.alpha = 1
self.volumeOffButton.alpha = 0
}
volumeTimer = Timer.scheduledTimer(timeInterval: 2.5, target: self, selector: #selector(fadeVolumeButton), userInfo: nil, repeats: false)
buttonTimer = Timer.scheduledTimer(timeInterval: 2.5, target: self, selector: #selector(fadePauseButton), userInfo: nil, repeats: false)
}
@objc func checkVolume() {
if UserDefaults.exists(key: "volumeOn") {
if(UserDefaults.standard.bool(forKey: "volumeOn") == false) {
self.queuePlayer?.isMuted = true
} else {
self.queuePlayer?.isMuted = false
}
} else {
self.queuePlayer?.isMuted = true
}
}
@objc func showControls() {
buttonTimer?.invalidate()
volumeTimer?.invalidate()
if(self.volumeOnButton.alpha > 0 || self.volumeOffButton.alpha > 0) {
UIView.animate(withDuration: 0.2) {
self.volumeOnButton.alpha = 0
self.volumeOffButton.alpha = 0
}
} else {
if UserDefaults.exists(key: "volumeOn") {
if(UserDefaults.standard.bool(forKey: "volumeOn") == false) {
UIView.animate(withDuration: 0.2) {
self.volumeOffButton.alpha = 1
self.volumeOnButton.alpha = 0
}
} else {
UIView.animate(withDuration: 0.2) {
self.volumeOffButton.alpha = 0
self.volumeOnButton.alpha = 1
}
}
} else {
UIView.animate(withDuration: 0.2) {
self.volumeOffButton.alpha = 1
self.volumeOnButton.alpha = 0
}
}
volumeTimer = Timer.scheduledTimer(timeInterval: 2.5, target: self, selector: #selector(fadeVolumeButton), userInfo: nil, repeats: false)
}
if(self.queuePlayer?.timeControlStatus == .playing) {
if(self.pauseButton.alpha > 0) {
UIView.animate(withDuration: 0.2) { self.pauseButton.alpha = 0 }
} else {
UIView.animate(withDuration: 0.2) { self.pauseButton.alpha = 1 }
buttonTimer = Timer.scheduledTimer(timeInterval: 2.5, target: self, selector: #selector(fadePauseButton), userInfo: nil, repeats: false)
}
} else if(self.queuePlayer?.timeControlStatus == .paused) {
if(self.playButton.alpha > 0) {
UIView.animate(withDuration: 0.2) { self.pauseButton.alpha = 0 }
} else {
UIView.animate(withDuration: 0.2) { self.playButton.alpha = 1 }
}
}
}
lazy var storage: Cache.Storage? = {
return try? Storage(diskConfig: diskConfig, memoryConfig: memoryConfig, transformer: TransformerFactory.forData())
}()
func loadVideo() {
// Trying to retrieve a track from cache asynchronously.
storage?.async.entry(forKey: mediaURL.absoluteString, completion: { result in
switch result {
case .error:
// The track is not cached.
print("Downloading from network")
self.playerItem = CachingPlayerItem(url: self.mediaURL)
case .value(let entry):
// The track is cached.
print("Downloading from cached library on device")
self.playerItem = CachingPlayerItem(data: entry.object, mimeType: "video/mp4", fileExtension: "mp4")
}
self.playerItem?.delegate = self
DispatchQueue.main.async {
if let playerItem = self.playerItem {
self.queuePlayer = AVQueuePlayer(items: [playerItem])
self.queuePlayer?.automaticallyWaitsToMinimizeStalling = false
self.playerLayer = AVPlayerLayer(player: self.queuePlayer)
self.playerLooper = AVPlayerLooper(player: self.queuePlayer!, templateItem: playerItem)
self.playerView.layer.addSublayer(self.playerLayer!)
self.playerLayer?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width * 1.25)
self.checkVolume()
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
} catch(let error) {
print(error.localizedDescription)
}
self.queuePlayer?.play()
self.queuePlayer?.addObserver(self, forKeyPath: "timeControlStatus", options: .initial, context:nil)
}
}
})
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if(keyPath == "timeControlStatus") {
if(self.playerView.isHidden && self.queuePlayer?.timeControlStatus == .playing) {
self.playerView.isHidden = false
}
}
}
var buttonTimer: Timer?
var volumeTimer: Timer?
@objc func playVideo() {
buttonTimer?.invalidate()
volumeTimer?.invalidate()
if(self.queuePlayer?.currentItem == nil) {
self.loadVideo()
}
if(self.queuePlayer?.timeControlStatus == .paused) {
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
} catch(let error) {
print(error.localizedDescription)
}
self.queuePlayer?.play()
}
self.playButton.alpha = 0
buttonTimer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(fadePauseButton), userInfo: nil, repeats: false)
volumeTimer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(fadeVolumeButton), userInfo: nil, repeats: false)
}
@objc func pauseVideo() {
buttonTimer?.invalidate()
self.queuePlayer?.pause()
self.playButton.alpha = 1
self.pauseButton.alpha = 0
self.volumeOnButton.alpha = 0
self.volumeOffButton.alpha = 0
}
@objc func fadePauseButton() {
UIView.animate(withDuration: 0.8) {
self.pauseButton.alpha = 0
}
}
@objc func fadeVolumeButton() {
UIView.animate(withDuration: 0.8) {
self.volumeOnButton.alpha = 0
self.volumeOffButton.alpha = 0
}
}
}
在我看来,问题应该出在loadVideo()
上面的某个地方。但是,我提供了自定义 UIView
VideoView 的所有代码,以避免任何错误或其他重要部分。谁能帮助我?会对我有很大帮助,因为我已经研究了好几个星期了。我已经尝试了每一个关于出列的建议,我已经尝试了所有我可以重用单元格的方法,......但都没有用。所以我想解决方案应该在AVPlayer
、Cache
库或CachingPlayerItem
库中找到。将不胜感激任何帮助或建议。提前谢谢你。
作为记录,我忘记了一些事情,但应该从代码中清楚:未显示 AVPlayer,因此最初未调用 loadVideo()
。仅当用户点击播放按钮 (playVideo()
) 时。如果我也不播放视频,一切都会顺利。照片显示正确,占位符显示正确,但视频在 我开始播放一个或多个视频(点击播放按钮,调用 playVideo()
,它调用 loadVideo()
)。
编辑:好的,我想通了。当单元格被重用时,视频本身似乎没有改变。我的意思是,在 loadVideo() 中,AVQueuePlayer() 被设置,这就是改变之后显示和播放的视频的原因。我觉得我需要设置这个 block :
// Trying to retrieve a track from cache asynchronously.
storage?.async.entry(forKey: mediaURL.absoluteString, completion: { result in
switch result {
case .error:
// The track is not cached.
print("Downloading from network")
DispatchQueue.main.async {
self.playerItem = CachingPlayerItem(url: self.mediaURL)
}
case .value(let entry):
// The track is cached.
print("Downloading from cached library on device")
DispatchQueue.main.async {
self.playerItem = CachingPlayerItem(data: entry.object, mimeType: "video/mp4", fileExtension: "mp4")
}
}
self.playerItem?.delegate = self
DispatchQueue.main.async {
if let playerItem = self.playerItem {
self.queuePlayer = AVQueuePlayer(items: [playerItem])
self.queuePlayer?.automaticallyWaitsToMinimizeStalling = false
self.playerLayer = AVPlayerLayer(player: self.queuePlayer)
self.playerLooper = AVPlayerLooper(player: self.queuePlayer!, templateItem: playerItem)
self.playerView.layer.addSublayer(self.playerLayer!)
self.playerLayer?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width * 1.25)
self.checkVolume()
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
} catch(let error) {
print(error.localizedDescription)
}
self.queuePlayer?.addObserver(self, forKeyPath: "timeControlStatus", options: .initial, context:nil)
}
}
})
在其他地方,在视频播放之前。因为这只会在点击播放按钮时被调用,但随后会显示错误的视频。已尝试直接在单元格中调用 loadVideo(),但似乎无法解决问题。我觉得我越来越近了。有什么想法吗?
最佳答案
不要将 AVQueuePlayer
存储在 tableView 单元格中。请记住,您可以保留的 AVPlayer 实例数量有上限。
将播放器本身、他们的配置、开始、暂停以及您拥有的任何其他操作移动到存储您的 UITableView
的 UIViewController
中。
当用户在 UITableViewCell
上按下播放时,您将通过 delegate
告诉 UIViewController
开始播放和 UIViewController
会做类似的事情:
AVQueuePlayer
AVQueuePlayer
插入UITableViewCell
不要忘记在重用单元格时从 UITableViewCell
中删除 AVQueuePlayer
关于ios - 对自定义 AVPlayer 的错误引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59225341/
我有一个 AVPlayer当我到达持续时间结束时,我想回到开始,但我不想重新启动AVPlayer . //Do something when video ended NotificationCente
我正在使用 AVPlayer 从服务器流式传输音频,我现在想做的是显示一个显示缓冲进度的自定义 UISlider。 有人想出这个吗?请给我解决方案。现在播放器一次加载整个持续时间并在 UISlider
我知道 AVPlayerItem(AVPlayer 的子类)能够订阅 AVPlayerItemDidPlayToEndTimeNotification AVPlayer 没有这样的功能,我需要使用 A
总结: 如果您只使用 AVPlayer 在您的应用程序中播放流音频,那么锁屏更新将工作得很好(许多流 - 一个接一个)。但是,如果您使用 AVPlayer 播放流式音频,然后播放本地视频文件(即使在使
我正在尝试创建像 Vine 这样的应用程序。我有一个 Collection View ,其中每个项目都包含一个带有 AVPlayerLayer 和 AVPlayer 实例的 View ,并且相应的 a
我创建了一个简单的 AVPlayer。 (如果我没有正确创建它,请帮我修复它...😀)我想用 swift ui 在我的 VStack 中显示它,但我有点卡住了... 如果库里至少有AVPlayer
我已将观察者添加到 AVPlayer,但它不会在 avplayer 状态准备好播放时调用该函数。该函数在视频开始播放时调用两次,但 AVPlayer 的持续时间参数都返回“nan”,我需要在 AVPl
我有 2 个 View Controller ,第一个包含一个视频信息列表表,然后从列表中选择一个项目,通过导航打开详细 View Controller 。我在这个细节 Controller 上使用了
关于这个主题的所有线程都非常老(5+ 哟),我似乎无法形成一个清晰的现代方法,所以希望这可以在 2020 年(Swift 5,Xcode 11)进行总结。 如果您要使用 为 iPhone 构建一个 A
我有一个 AVPlayer 可以从网络流式传输 mp3 文件。我已经激活了一个 AVAudioSession 以便在应用程序退出/屏幕关闭时播放音频。音乐播放完美,但手机顶部状态菜单中出现的“播放”三
我正在使用 Apple 的文档演示。这是演示链接: AVPlayerDemo 我的应用程序在执行以下步骤后崩溃了: 1) 播放歌曲 2) 从搜索栏快进。 3)点击下一步,4) 从搜索栏快进。 这是我的
因此看来,实际起作用的唯一值是0.0、0.5、1.0和2.0 ... 我尝试将其设置为0.25,因为我希望它以自然速度的1/4播放,但它却以自然速度的1/2播放。有人可以确认吗? 最佳答案 已确认。实
我有一个应用程序,它通过 AVMutableComposition 将本地文件加载到 avPlayer 中,它可能有多达 6 个音频和视频轨道作为合成的一部分。 我有一个 UISlider,用于调整播
在我的 IOS 应用程序中使用 AVPlayer 显示短视频的屏幕。我成功离开并重新进入此屏幕几次,但在七次或更多次后,我得到空白屏幕并且 AVPlayerLayer 的 IsReadyForDisp
我正在开发一个应用程序,其中包括使用每帧动画播放视频的功能。 您可以看到 example这样的功能。 我已经尝试添加 CAKeyFrameAnimation到 AVSynchronizedLayer
如何在 osx 自动播放中制作 avplayer? 我试过这个: NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"video nam
iOS AVPlayer 的默认最大和最小缓冲区大小是多少?如何增加 mp3 流媒体的大小?谢谢你 最佳答案 如果您的 缓冲区大小 意味着播放缓冲区,那么我相信这个大小没有记录。 此行为由 AVFou
我正在使用多个 AVPlayer 在我的屏幕上显示内容,并且它们都同时播放视频。 问题是有时 avplayer 正在播放,但 avplayerlayer 没有显示任何内容 - 你得到的只是一个空白屏幕
我正在使用 AVPlayer 在我的应用程序中播放视频,现在我想让视频在后台模式下播放。 这是我放入 - (BOOL)application:(UIApplication *)application
我在 iOS 6.1 中使用 AVPlayer 对象。我目前正在连接到 Icecast 服务器以传输现场音乐源。但是,当流由于任何原因(例如重新启动或信号更改)而中断时,AVPlayer 会停止播放。
我是一名优秀的程序员,十分优秀!