如何在Swift中使用AVPlayerViewController (AVKit)播放视频

189

如何使用 AV Kit Player View Controller 在 Swift 中播放视频?

override func viewDidLoad() {
        super.viewDidLoad()
        let videoURLWithPath = "http://****/5.m3u8"
        let videoURL = NSURL(string: videoURLWithPath)
        playerViewController = AVPlayerViewController()

        dispatch_async(dispatch_get_main_queue()) {
            self.playerViewController?.player = AVPlayer.playerWithURL(videoURL) as AVPlayer
        }
    }

要使用AVPlayer(没有控件),请参见此答案 - Suragch
15个回答

593

SwiftUI

import SwiftUI
import AVKit

struct ContentView: View {
    var body: some View {
        let videoURL = URL(string: "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_5MB.mp4")
        let player = AVPlayer(url: videoURL!)
        VideoPlayer(player: player)
    }
}

Swift 3.x-5.x

必要条件:导入AVKit导入AVFoundation

即使使用AVPlayer,也需要AVFoundation框架

如果想要使用AVPlayerViewController

let videoURL = URL(string: "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_5MB.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
    playerViewController.player!.play()
}

或者只使用AVPlayer

let videoURL = URL(string: "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_5MB.mp4")
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()

最好把这段代码放到方法中:override func viewDidAppear(_ animated: Bool) 或之后的某个地方。

Objective-C

AVPlayerViewController:

目标-C

AVPlayerViewController

NSURL *videoURL = [NSURL URLWithString:@"https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_5MB.mp4"];
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
playerViewController.player = player;
[self presentViewController:playerViewController animated:YES completion:^{
  [playerViewController.player play];
}];

或者只是AVPlayer

NSURL *videoURL = [NSURL URLWithString:@"https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_5MB.mp4"];
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:playerLayer];
[player play];

@pikis 感谢您提供的代码示例。奇怪的是,我们按照所写的方式尝试使用AVPlayerController时,在 [self presentViewController:playerViewController animated:YES completion:nil]; 这一行代码上遇到了SIGABRT错误。 - Praxiteles
8
需要导入AVFoundation库。 - Rich Fox
1
@Nick89,AVPlayer在处理直接链接时工作正常,但如果您需要使用像YouTube、Vimeo等(具有间接链接)的服务,则应使用它们自己的库或SDK。(例如,对于YouTube:指南)。 - pkis
2
指令的顺序很重要,我还需要导入AVKit。 - htafoya
Objective-C 版本有一个不必要的行(可能是拒绝):[self.view addSubview: playerViewController.view] 应该被移除; - Jim75
显示剩余12条评论

31

试试这个,绝对可以在 Swift 2.0 中使用

 let player = AVPlayer(URL: url)
    let playerController = AVPlayerViewController()

    playerController.player = player
    self.addChildViewController(playerController)
    self.view.addSubview(playerController.view)
    playerController.view.frame = self.view.frame

    player.play()  

1
谢谢。addChildViewController使它嵌入了我想要的内容。 :) - SDW
1
嵌入确实可以无缝运行,但是你如何处理方向变化呢?比如说,在纵向模式下,播放器占据了屏幕的一半,而视图控制器仅支持纵向,但视频可以像大多数应用程序(如YouTube、Vimeo等)一样在纵向模式下查看。 - Abid Hussain
注意:addChildViewController是必要的。我尝试过没有它,然后它“几乎”可以工作-它播放一次,扩展到全屏。但它不会再次播放,也无法退出全屏模式。因此,子视图控制器是必要的。 - n13
self.addChildViewController(playerController) 现在变成了 self.addChild(playerController),供您参考。 - Marquis103

13

Swift 5+

首先,在视图控制器中全局定义两个变量。

var player: AVPlayer!
var playerViewController: AVPlayerViewController!

我在这里将播放器添加到所需的视图中。

@IBOutlet weak var playerView: UIView!

然后将以下代码添加到 viewDidLoad 方法中。

let videoURL = URL(string: "videoUrl")
self.player = AVPlayer(url: videoURL!)
self.playerViewController = AVPlayerViewController()
playerViewController.player = self.player
playerViewController.view.frame = self.playerView.frame
playerViewController.player?.pause()
self.playerView.addSubview(playerViewController.view)
如果您没有将playerplayerViewController全局定义,您将无法嵌入播放器。

我正在使用Swift 5,所有在应用程序启动后立即在UIView中播放视频的第一次尝试(我有Scenekit和UI组件的混合)都导致黑屏无反应。似乎真的需要全局定义变量。像魅力一样工作。这个例子真的很好。 - ZAY
1
非常好的回答!谢谢。 - atereshkov

12

Swift 3.0完整源代码:

import UIKit
    import AVKit
    import AVFoundation

    class ViewController: UIViewController,AVPlayerViewControllerDelegate
    {
        var playerController = AVPlayerViewController()


        @IBAction func Play(_ sender: Any)
        {
            let path = Bundle.main.path(forResource: "video", ofType: "mp4")

            let url = NSURL(fileURLWithPath: path!)

            let player = AVPlayer(url:url as URL)

            playerController = AVPlayerViewController()


            NotificationCenter.default.addObserver(self, selector: #selector(ViewController.didfinishplaying(note:)),name:NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem)

            playerController.player = player

            playerController.allowsPictureInPicturePlayback = true

            playerController.delegate = self

            playerController.player?.play()

            self.present(playerController,animated:true,completion:nil)
        }

        func didfinishplaying(note : NSNotification)
        {
            playerController.dismiss(animated: true,completion: nil)
            let alertview = UIAlertController(title:"finished",message:"video finished",preferredStyle: .alert)
            alertview.addAction(UIAlertAction(title:"Ok",style: .default, handler: nil))
            self.present(alertview,animated:true,completion: nil)
        }


        func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
                let currentviewController =  navigationController?.visibleViewController

                if currentviewController != playerViewController
                {
                    currentviewController?.present(playerViewController,animated: true,completion:nil)
                }


            }
    }

你好Ronak,感谢你介绍了Swift中的观察者来处理视频结束! 我尝试使用你提供的代码创建AVPlayerViewController,但无法使其正常工作(第一个代码片段上方的答案),有什么不同之处?我错过了什么或应该实现什么以使你的方法中的观察者起作用? - Manu

12

试试这个

var player:AVPlayer!
var avPlayerLayer:AVPlayerLayer = AVPlayerLayer(player: player)
avPlayerLayer.frame = CGRectMake(your frame)
self.view.layer .addSublayer(avPlayerLayer)
var steamingURL:NSURL = NSURL(string:playerURL)
player = AVPlayer(URL: steamingURL)
player.play()

当我运行这段代码时,我得到了一个空的视图控制器。 - orazz
1
@Oneperson 好的,设置 avPlayerLayer.frame = CGRectMake(50,50,100,100)。 - Ramesh
代码 var player:AVPlayer! var playerItem:AVPlayerItem!; var avPlayerLayer:AVPlayerLayer = AVPlayerLayer(player: player) avPlayerLayer.frame = CGRectMake(50,50,100,100) self.view.layer .addSublayer(avPlayerLayer) let videoURLWithPath = "http://*****/45.m3u8" var steamingURL:NSURL = NSURL(string: videoURLWithPath) player = AVPlayer(URL: steamingURL) player.play() - orazz
@Oneperson http://edge.tolkun.tv/45.m3u8无法使用。您能提供完整的URL吗? - Ramesh
@Oneperson 这个 URL 不可用,请在浏览器中检查。 - Ramesh
显示剩余4条评论

7

Objective C

这只适用于Xcode 7

打开.h文件并导入AVKit/AVKit.hAVFoundation/AVFoundation.h。然后在.m文件中添加以下代码:

NSURL *url=[[NSBundle mainBundle]URLForResource:@"arreg" withExtension:@"mp4"];
AVPlayer *video=[AVPlayer playerWithURL:url];
AVPlayerViewController *controller=[[AVPlayerViewController alloc]init];
controller.player=video;
[self.view addSubview:controller.view];
controller.view.frame=self.view.frame;
[self addChildViewController:controller];
[video play];

5

使用 MPMoviePlayerController:

 import UIKit
 import MediaPlayer

 class ViewController: UIViewController {

     var streamPlayer : MPMoviePlayerController =  MPMoviePlayerController(contentURL: NSURL(string:"video url here"))
     override func viewDidLoad() {
         super.viewDidLoad()
         streamPlayer.view.frame = self.view.bounds
         self.view.addSubview(streamPlayer.view)

         streamPlayer.fullscreen = true
         // Play the movie!
         streamPlayer.play()
}
}

使用 AVPlayer:

import AVFoundation

var playerItem:AVPlayerItem?
var player:AVPlayer?

override func viewDidLoad() {
        super.viewDidLoad() 
      let url = NSURL(string: "url of the audio or video") 
      playerItem = AVPlayerItem(URL: url!)
      player=AVPlayer(playerItem: playerItem!)
      let playerLayer=AVPlayerLayer(player: player!)
      playerLayer.frame=CGRectMake(0, 0, 300, 50)
      self.view.layer.addSublayer(playerLayer)
}

我有一个播放按钮来处理按钮的点击。

playButton.addTarget(self, action: "playButtonTapped:", forControlEvents: .TouchUpInside)

func playButtonTapped(sender: AnyObject) {
        if player?.rate == 0
        {
            player!.play()
            playButton.setImage(UIImage(named: "player_control_pause_50px.png"), forState: UIControlState.Normal)
        } else {
            player!.pause()
            playButton.setImage(UIImage(named: "player_control_play_50px.png"), forState: UIControlState.Normal)
        }
    }

我已经添加了一个观察者来监听AVPlayerItemDidPlayToEndTimeNotification。

override func viewWillAppear(animated: Bool) {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "finishedPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem)
    }

override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

当视频/音频播放完成时,重置按钮图像和通知。

  func finishedPlaying(myNotification:NSNotification) {
        playButton.setImage(UIImage(named: "player_control_play_50px.png"), forState: UIControlState.Normal)

        let stopedPlayerItem: AVPlayerItem = myNotification.object as! AVPlayerItem
        stopedPlayerItem.seekToTime(kCMTimeZero)
    }

2
MPMoviePlayerController已被弃用,我们可能不应再使用它了。 - Skywalker
请您能否举一个不使用URL的例子,例如使用本地视频。 - nyxee

4
iOS10/Swift3/Xcode 8中出现了一个错误(?!)?
if let url = URL(string: "http://devstreaming.apple.com/videos/wwdc/2016/102w0bsn0ge83qfv7za/102/hls_vod_mvp.m3u8"){
    let playerItem = AVPlayerItem(url: url)
    let player = AVPlayer(playerItem: playerItem)
    let playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame=CGRect(x: 10, y: 10, width: 300, height: 300)
    self.view.layer.addSublayer(playerLayer)
}

不起作用(空的矩形...)

这个有效:

if let url = URL(string: "http://devstreaming.apple.com/videos/wwdc/2016/102w0bsn0ge83qfv7za/102/hls_vod_mvp.m3u8"){

            let player = AVPlayer(url: url)
            let controller=AVPlayerViewController()
            controller.player=player
            controller.view.frame = self.view.frame
            self.view.addSubview(controller.view)
            self.addChildViewController(controller)
            player.play()
        }

Same URL...


self.view.layer.addSublayer(playerLayer) 之后添加这一行代码:player.play(),然后再试一次。 - orazz

4

Swift 3:

import UIKit
import AVKit
import AVFoundation

class ViewController: UIViewController {

    @IBOutlet weak var viewPlay: UIView!
    var player : AVPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        let url : URL = URL(string: "http://static.videokart.ir/clip/100/480.mp4")!
        player = AVPlayer(url: url)
        let playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = self.viewPlay.bounds
        self.viewPlay.layer.addSublayer(playerLayer)

    }

    @IBAction func play(_ sender: Any) {
        player?.play()
    }

    @IBAction func stop(_ sender: Any) {
        player?.pause()
    }

}

你的回答中哪里使用了 AVPlayerViewController - Anjan Biswas

2

这对我在 Swift 5 中起作用

刚刚从样本视频将示例视频添加到项目中

使用以下Swift代码示例为播放来自网站和本地的视频添加了操作按钮。

import UIKit
import AVKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //TODO : Make Sure Add and copy "SampleVideo.mp4" file in project before play
    }

    @IBAction func playWebVideo(_ sender: Any) {

        guard let url = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4") else {
            return
        }
        // Create an AVPlayer, passing it the HTTP Live Streaming URL.
        let player = AVPlayer(url: url)
        let controller = AVPlayerViewController()
        controller.player = player
        present(controller, animated: true) {
            player.play()
        }
    }

    @IBAction func playLocalVideo(_ sender: Any) {

        guard let path = Bundle.main.path(forResource: "SampleVideo", ofType: "mp4") else {
            return
        }
        let videoURL = NSURL(fileURLWithPath: path)

        // Create an AVPlayer, passing it the local video url path
        let player = AVPlayer(url: videoURL as URL)
        let controller = AVPlayerViewController()
        controller.player = player
        present(controller, animated: true) {
            player.play()
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接