191

How do you play a video with AV Kit Player View Controller in 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
        }
    }
1
  • For using AVPlayer (doesn't have the controls), see this answer.
    – Suragch
    Commented Nov 21, 2017 at 13:27

15 Answers 15

599

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

Necessary: import AVKit, import AVFoundation

AVFoundation framework is needed even if you use AVPlayer

If you want to use 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()
}

or just 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()

It's better to put this code into the method: override func viewDidAppear(_ animated: Bool) or somewhere after.


Objective-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];
}];

or just 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];
17
  • @pikis Thanks for the code example. Strange, we tried the AVPlayerController as written and get a SIGABRT on: [self presentViewController:playerViewController animated:YES completion:nil];
    – Praxiteles
    Commented Jul 16, 2015 at 0:03
  • @Praxiteles, it works on iOS8 or later, maybe it is the reason.
    – pkis
    Commented Jul 16, 2015 at 10:57
  • 8
    Also required import AVFoundation for me
    – Rich Fox
    Commented Oct 14, 2015 at 18:25
  • 1
    @Nick89, AVPlayer works correct with direct links, but if you need to use services like YouTube, Vimeo, etc.(that have indirect links), you should use their own library or SDK. (e.g. for YouTube: guide).
    – pkis
    Commented Jan 11, 2016 at 7:53
  • 2
    The order of the instructions is important, also I needed to import AVKit
    – htafoya
    Commented May 23, 2017 at 19:00
32

Try this, definitely works for 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()  
4
  • 1
    Thanks. The addChildViewController made it embedded just what I want. :)
    – SDW
    Commented Mar 16, 2016 at 17:19
  • 1
    Embedding does work flawlessly but how will you handle orientation changes? Let say player takes half of screen in portrait and view controller only supports portrait but video can be seen in portrait like most apps do e.. youtube, vimeo etc. Commented Jun 1, 2016 at 13:45
  • Note: addChildViewController is necessary. I tried without that and then it almost works - it plays once, it expands to full screen. But it doesn't play again, or get out of full screen mode. So child view controller is necessary.
    – n13
    Commented Nov 25, 2016 at 10:46
  • self.addChildViewController(playerController) is now self.addChild(playerController) fyi
    – Marquis103
    Commented Apr 29, 2019 at 4:51
14

Swift 5+

First of all you have to define 2 variables globally inside your view controller.

var player: AVPlayer!
var playerViewController: AVPlayerViewController!

Here I'm adding player to a desired view.

@IBOutlet weak var playerView: UIView!

Then add following code to the viewDidLoad method.

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)

If you are not defining player and playerViewController globally, you won't be able to embed player.

2
  • I am using Swift 5 and all my first try's to play a video right after application startup inside the UIView (I have a mix of Scenekit and UI Components) resulted in a black screen doing nothing. It seems it's really necessary to define the variables globally. Works like charm. This example is really a good one.
    – ZAY
    Commented May 18, 2021 at 16:20
  • 1
    Great answer! Thanks.
    – atereshkov
    Commented Oct 4, 2021 at 11:35
12

Try This

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()
9
  • When I run this code i get the empty view controller
    – orazz
    Commented Sep 19, 2014 at 13:17
  • @Oneperson you set avPlayerLayer frame ?
    – Ramesh
    Commented Sep 19, 2014 at 13:19
  • 1
    @Oneperson ok set this avPlayerLayer.frame = CGRectMake(50,50,100,100)
    – Ramesh
    Commented Sep 19, 2014 at 13:25
  • code 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() code
    – orazz
    Commented Sep 19, 2014 at 13:34
  • @Oneperson edge.tolkun.tv/45.m3u8 is not working. can you give your full url
    – Ramesh
    Commented Sep 19, 2014 at 13:38
12

Swift 3.0 Full source code:

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)
                }


            }
    }
1
  • Hello ronak, thank you for introducing the observers in swift to handle the end of the video!! I didn't managed to make it work by creating the AVPlayerViewController with the code provided from the answer on top of yours (first code snippet), what is different? What I missed or should implement in order to make the observer in your methods work?
    – Manu
    Commented Oct 26, 2018 at 4:05
7

Objective c

This only works in Xcode 7

Go to .h file and import AVKit/AVKit.h and AVFoundation/AVFoundation.h. Then go .m file and add this code:

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

Using 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()
}
}

Using 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)
}

I have a play button to handle button tap.

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)
        }
    }

I have added an observer listening for 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)
    }

When video/audio play is finished, reset button image and notification

  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
  • 3
    MPMoviePlayerController is deprecated and we should probably not use it anymore.
    – Skywalker
    Commented Mar 11, 2016 at 15:46
  • can u please give an example not using URLs, for examle using a local video.
    – nyxee
    Commented Jul 13, 2017 at 0:33
5

a bug(?!) in 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)
}

does not work (empty rect...)

this works:

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...

1
  • add this line: player.play() after: self.view.layer.addSublayer(playerLayer) and try again
    – orazz
    Commented Aug 29, 2016 at 12:25
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()
    }

}
1
  • Where in your answer did you use AVPlayerViewController? Commented Jan 16, 2018 at 19:29
2

This worked for me in Swift 5

Just added sample video to the project from Sample Videos

Added action Buttons for playing videos from Website and Local with the following swift code example

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()
        }
    }

}
1
let videoUrl = //URL: Your Video URL

//Create player first using your URL
let yourplayer = AVPlayer(url: videoUrl)

//Create player controller and set it’s player
let playerController = AVPlayerViewController()
playerController.player = yourplayer


//Final step To present controller  with player in your view controller
present(playerController, animated: true, completion: {
   playerController.player!.play()
})
1

Swift 5.0

Improved from @ingconti answer . This worked for me.

 if let url = URL(string: "urUrlString"){
            let player = AVPlayer(url: url)
            let avController = AVPlayerViewController()
            avController.player = player
            // your desired frame
            avController.view.frame = self.view.frame
            self.view.addSubview(avController.view)
            self.addChild(avController)
            player.play()
        }
1

Custom VideoPlayer using ASVideoPlayer Library from github link : https://github.com/Asbat/ASVideoPlayer

// --------------------------------------------------------
// MARK:- variables
// --------------------------------------------------------

var videoPlayer = ASVideoPlayerController()
var videoData : [VideoModel] = []
var allVideoData : [AllVideoModel] = []
var cellHeights = [IndexPath: CGFloat]()
let loadingCellTableViewCellCellIdentifier = "LoadingCellTableViewCell"
var pauseIndexPath : Int = 0
var pageNumber = 1
var index = 0
var id = ""
var titleVideo = ""
var isUpdate = false
var myVideo : [MyVideo] = []
var imgs = [UIImage]()
var activityViewController : UIActivityViewController!

private var activityIndicator = NVActivityIndicatorView(frame: CGRect(x: 5, y: 5, width: 5, height: 5), type: .circleStrokeSpin, color: .systemBlue, padding: 5)
private let refreshControl = UIRefreshControl()


// --------------------------------------------------------
// MARK:- Outlets
// --------------------------------------------------------
@IBOutlet private var tableVideo: UITableView!
@IBOutlet private var _btnBack: UIButton!
@IBOutlet var _btnide: UIButton!

// ---------------------------------------------------------
// MARK:- Lifecycle
// ---------------------------------------------------------

override func viewDidLoad() {
    super.viewDidLoad()
    
    self._btnide.isHidden = true
    tableVideo.rowHeight = UITableView.automaticDimension
    tableVideo.separatorStyle = .none
    tableVideo.delegate = self
    tableVideo.dataSource = self
    tableVideo.register(UINib(nibName: "VideoPlayerTableCell", bundle: nil), forCellReuseIdentifier: "VideoPlayerTableCell")
    let cellNib = UINib(nibName:loadingCellTableViewCellCellIdentifier, bundle: nil)
    tableVideo.register(cellNib, forCellReuseIdentifier: loadingCellTableViewCellCellIdentifier)
    navigationController?.navigationBar.isHidden = true
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    ASVideoPlayerController.sharedVideoPlayer.pausePlayeVideosFor(tableView: tableVideo)
    tableVideo.scrollToRow(at: IndexPath(row: index, section: 0), at: .none, animated: true)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    tableVideo.scrollToRow(at: IndexPath(row: pauseIndexPath, section: 0), at: .none, animated: true)
    puasVideoWhenPushVC(index: pauseIndexPath)
    NotificationCenter.default.removeObserver(self)
    if tableVideo.isHidden == true {
    }
}

@IBAction func _onTapBackBtnAction(_ sender: UIButton) {
    tableVideo.scrollToRow(at: IndexPath(row: pauseIndexPath, section: 0), at: .none, animated: true)
    self.puasVideoWhenPushVC(index: pauseIndexPath)
    navigationController?.popViewController(animated: true)
    navigationController?.navigationBar.isHidden = false
}

// ---------------------------------------------------------------------
// MARK:- TableView Delegate & DataSource
// ---------------------------------------------------------------------

  extension VideoPlayerVC : 
  UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate {

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if isUpdate{
        return videoData.count
    }else{
        return allVideoData.count
    }
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if tableView == tableVideo {
        return view.bounds.height
    }else {
        return UITableView.automaticDimension
    }
}


func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if tableView == tableVideo {
        if let videoCell = cell as? ASAutoPlayVideoLayerContainer, let _ = videoCell.videoURL {
            ASVideoPlayerController.sharedVideoPlayer.removeLayerFor(cell: videoCell)
        }
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableVideo.dequeueReusableCell(withIdentifier: "VideoPlayerTableCell", for: indexPath) as! VideoPlayerTableCell
    if isUpdate{
        self.id = videoData[indexPath.row].id ?? ""
        cell.configureCell(videoUrl: videoData[indexPath.row].videoLink )
    }else{
        self.id = allVideoData[indexPath.row].id ?? ""
        cell.configureCell(videoUrl: allVideoData[indexPath.row].videoLink)
    }
    cell.btnPlayPause.isSelected = false
    cell.btnPlayPause.tag = indexPath.row
    cell.btnPlayPause.addTarget(self, action: #selector(didTapPlayPauseButton(_:)), for: .touchUpInside)
    cell.btnPlayPause.setImage(UIImage(named: ""), for: .normal)
    cell.btnPlayPause.setImage(UIImage(named: "btn_play_video"), for: .selected)
    
    cell.btnUseNow.tag = indexPath.row
    cell.btnUseNow.addTarget(self, action: #selector(btnUseNowTapped(sender:)), for: .touchUpInside)
    
    cell.btnShare.tag = indexPath.row
    cell.btnShare.addTarget(self, action: #selector(btnShareTapped(sender:)), for: .touchUpInside)
    
    cell.btnSave.tag = indexPath.row
    cell.btnSave.addTarget(self, action: #selector(btnSaveTapped(sender:)), for: .touchUpInside)
    
    pauseIndexPath = indexPath.row
    return cell
}

@objc func btnUseNowTapped(sender: UIButton){
    
    self._btnide.isHidden = false
    self.pausePlayeVideos()
    let editVC = EditVideoVC()
    var fileName : String = kEmptyString
    
    if self.isUpdate{
        editVC.videoString = self.videoData[sender.tag].videoLink ?? kEmptyString
        editVC.id = self.videoData[sender.tag].id ?? kEmptyString
        editVC.titleVideo = self.videoData[sender.tag].title ?? kEmptyString
        fileName = self.videoData[sender.tag].videoZip ?? kEmptyString
        
        guard !FileManager.isExist(id: self.videoData[sender.tag].id ?? kEmptyString) else{
            print("File Downloaded")
            self.puasVideoWhenPushVC(index: sender.tag)
            self.navigationController?.pushViewController(editVC, animated: true)
            return }
        
        FileManager.download(id: self.videoData[sender.tag].id ?? kEmptyString, url: fileName) { (url) in
            guard url != nil else {
                print("not download")
                return
            }
            self.puasVideoWhenPushVC(index: sender.tag)
            self.navigationController?.pushViewController(editVC, animated: true)
        }
    }
    else{
        editVC.videoString = self.allVideoData[sender.tag].videoLink ?? kEmptyString
        editVC.id = self.allVideoData[sender.tag].id ?? kEmptyString
        editVC.titleVideo = self.allVideoData[sender.tag].title ?? kEmptyString
        fileName = self.allVideoData[sender.tag].videoZip ?? kEmptyString
        
        guard !FileManager.isExist(id: self.allVideoData[sender.tag].id ?? kEmptyString) else{
            print("File Downloaded")
            self.puasVideoWhenPushVC(index: sender.tag)
            self.navigationController?.pushViewController(editVC, animated: true)
            return }
        
        FileManager.download(id: self.allVideoData[sender.tag].id ?? kEmptyString, url: fileName) { (url) in
            guard url != nil else {
                print("not download")
                return
            }
            self.puasVideoWhenPushVC(index: sender.tag)
            self.navigationController?.pushViewController(editVC, animated: true)
        }
    }
}

@objc func btnShareTapped(sender: UIButton){
    
    if self.isUpdate{
        let video = ["\(String(describing: self.videoData[sender.tag].videoLink))"]
        self.activityViewController = UIActivityViewController(activityItems: video, applicationActivities: nil)
        self.activityViewController.setValue("Video Share", forKey: "subject")
        
        self.activityViewController.popoverPresentationController?.sourceView = self.view
        self.activityViewController.excludedActivityTypes = [ UIActivity.ActivityType.airDrop, UIActivity.ActivityType.postToTwitter, UIActivity.ActivityType.addToReadingList, UIActivity.ActivityType.assignToContact,UIActivity.ActivityType.copyToPasteboard,UIActivity.ActivityType.mail,UIActivity.ActivityType.markupAsPDF,UIActivity.ActivityType.message,UIActivity.ActivityType.postToFacebook,UIActivity.ActivityType.postToFlickr,UIActivity.ActivityType.postToTencentWeibo,UIActivity.ActivityType.postToVimeo,UIActivity.ActivityType.postToWeibo,UIActivity.ActivityType.saveToCameraRoll]
        self.present(self.activityViewController, animated: true, completion: nil)
    }
    else{
        let categoryVideo = ["\(String(describing: self.allVideoData[sender.tag].videoLink))"]
        self.activityViewController = UIActivityViewController(activityItems: categoryVideo, applicationActivities: nil)
        self.activityViewController.setValue("Video Share", forKey: "subject")
        
        self.activityViewController.popoverPresentationController?.sourceView = self.view
        self.activityViewController.excludedActivityTypes = [ UIActivity.ActivityType.airDrop, UIActivity.ActivityType.postToTwitter]
        self.present(self.activityViewController, animated: true, completion: nil)
    }
}

@objc func btnSaveTapped(sender: UIButton){
   
    if self.isUpdate{
        self.downloadVideos(video: self.videoData[sender.tag].videoLink ?? kEmptyString)
    }else{
        self.downloadVideos(video: self.allVideoData[sender.tag].videoLink ?? kEmptyString)
    }
}


private func downloadVideos(video : String){
    Alamofire.request(video).downloadProgress(closure : { (progress) in
    }).responseData{ (response) in
        ///# Create folder in documetn directory #///

        if let data = response.result.value{
            let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("Videos")
            if !FileManager.default.fileExists(atPath: path) {
                try! FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
            }
            let fileURL = URL(fileURLWithPath:path).appendingPathComponent("\(self.id)/\(self.titleVideo)/output.mp4")
            print(fileURL)
            do{
                try data.write(to: fileURL, options: .atomic)
            }catch{
                print("could not download")
            }
            print(fileURL)
        }
    }
}


// ----------------------------------------------------------------------
// MARK:- Scrollview Method
// ----------------------------------------------------------------------

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    if scrollView == tableVideo {
        pauseIndexPath = Int(scrollView.contentOffset.y / scrollView.frame.size.height)
        pausePlayeVideos()
    }
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if scrollView == tableVideo {
        if !decelerate {
            pausePlayeVideos()
        }
    }
}

// ----------------------------------------------------------------------
// MARK:- Function Pause & Play Button
// ----------------------------------------------------------------------

func puasVideoWhenPushVC (index : NSInteger) {
    if isUpdate{
        guard let cell = tableVideo.cellForRow(at: IndexPath(row: index, section: 0)) as? VideoPlayerTableCell else { return }
        ASVideoPlayerController.sharedVideoPlayer.pauseVideo(forLayer: cell.videoLayer, url: videoData[index].videoLink ?? "")
    }
    else{
        guard let cell = tableVideo.cellForRow(at: IndexPath(row: index, section: 0)) as? VideoPlayerTableCell else { return }
        ASVideoPlayerController.sharedVideoPlayer.pauseVideo(forLayer: cell.videoLayer, url: allVideoData[index].videoLink ?? "")
    }
}

@objc func pausePlayeVideos(){
    ASVideoPlayerController.sharedVideoPlayer.pausePlayeVideosFor(tableView: tableVideo)
}

@objc func appEnteredFromBackground() {
    ASVideoPlayerController.sharedVideoPlayer.pausePlayeVideosFor(tableView: tableVideo, appEnteredFromBackground: true)
}

@objc func didTapPlayPauseButton(_ sender: UIButton) {
    
    guard let cell = tableVideo.cellForRow(at: IndexPath(row: sender.tag, section: 0)) as? VideoPlayerTableCell else { return }
    if sender.isSelected {
        if isUpdate{
            ASVideoPlayerController.sharedVideoPlayer.playVideo(withLayer: cell.videoLayer, url: videoData[sender.tag].videoLink ?? "")
        }else{
            ASVideoPlayerController.sharedVideoPlayer.playVideo(withLayer: cell.videoLayer, url: allVideoData[sender.tag].videoLink ?? "")
        }
    } else {
        if isUpdate{
            ASVideoPlayerController.sharedVideoPlayer.pauseVideo(forLayer: cell.videoLayer, url: videoData[sender.tag].videoLink ?? "")
        }else{
            ASVideoPlayerController.sharedVideoPlayer.pauseVideo(forLayer: cell.videoLayer, url: allVideoData[sender.tag].videoLink ?? "")
        }
    }
    sender.isSelected = !sender.isSelected
}
0

Swift 5

  @IBAction func buttonPressed(_ sender: Any) {
    let videoURL = course.introductionVideoURL
    let player = AVPlayer(url: videoURL)
    let playerViewController = AVPlayerViewController()
    playerViewController.player = player

    present(playerViewController, animated: true, completion: {

        playerViewController.player!.play()
    })

// here the course includes a model file, inside it I have given the url, so I am calling the function from model using course function.

// also introductionVideoUrl is a URL which I declared inside model .

 var introductionVideoURL: URL

Also alternatively you can use the below code instead of calling the function from model

Replace this code

  let videoURL = course.introductionVideoURL

with

  guard let videoURL = URL(string: "https://something.mp4) else {
        return
0

If you want to play video with AVPlayer with some UI customization than better to involve storyboard also... like taking the full screen when video is playing (like snapchat)... use thumbnail image until the video is ready to play... and can easily add gestures like dismiss on drag ... or stop video when user press and hold ...

import UIKit
import AVKit
import AVFoundation

class CustomVideoPlayer: BaseViewController {
    
    @IBOutlet weak var videoThumbNail: UIImageView! //to show thumbnail image until the video is ready to play 
    @IBOutlet weak private var videoView: UIView! // uiview that's going to play the video 
    
    private var observer: NSKeyValueObservation?
    
    var thumbNailURL = ""
    var videoURL = ""
    
    // MARK: - Properties
    private var player: AVPlayer!
    private var playerLayer: AVPlayerLayer!
    private var isVideoPlaying = false
    private var isPlayerViewHide = true
    private var puseTime: CMTime = .zero
    private var timer: Timer?
    
    //to remove on drop gesture
    var panGestureRecognizer: UIPanGestureRecognizer?
    var originalPosition: CGPoint?
    var currentPositionTouched: CGPoint?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupThumbnail()
        setupPlayer()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        //video again play when app comes from background
        let nc = NotificationCenter.default
        nc.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
        nc.addObserver(self, selector: #selector(appMovedToForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
        
        //remove VC to drag
        panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panGestureAction(_:)))
        view.addGestureRecognizer(panGestureRecognizer!)
    }
    
    //drag down gesture to dismiss video viewcontroller
    @objc func panGestureAction(_ panGesture: UIPanGestureRecognizer) {
        let translation = panGesture.translation(in: view)
        
        if panGesture.state == .began {
          originalPosition = view.center
          currentPositionTouched = panGesture.location(in: view)
        } else if panGesture.state == .changed {
            view.frame.origin = CGPoint(
              x: translation.x,
              y: translation.y
            )
        } else if panGesture.state == .ended {
          let velocity = panGesture.velocity(in: view)

          if velocity.y >= 1500 {
            UIView.animate(withDuration: 0.2
              , animations: {
                self.view.frame.origin = CGPoint(
                  x: self.view.frame.origin.x,
                  y: self.view.frame.size.height
                )
            }, completion: { [weak self] (isCompleted) in
                if isCompleted {
                    self?.dismiss(animated: false, completion: nil)
                    self?.player.replaceCurrentItem(with: nil)
                }
            })
          } else {
            UIView.animate(withDuration: 0.2, animations: {
              self.view.center = self.originalPosition!
            })
          }
            
        }
      }
    
    @objc func appMovedToBackground() {
        print("video player is in background")
    }

    // again play video if user coming from background 
    @objc func appMovedToForeground() {
        print("video player is in foreground")
        self.player?.play()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        playerLayer.frame = videoView.bounds
    }
    
    //set thumbnail 
    private func setupThumbnail(){
        showProgressIndicator(view: self.view)
        videoThumbNail.contentMode = .scaleAspectFill
        videoThumbNail.setImage(WithUrlString: thumbNailURL)
        
    }
    
    private func setupPlayer() {
        
        guard let videoURL = URL(string: videoURL) else {
            return
        }
        player = AVPlayer(url: videoURL)
        
        let asset = AVAsset(url: videoURL)
        
        let assetKeys = [
            "playable",
            "hasProtectedContent"
        ]
        
        // Create a new AVPlayerItem with the asset and an
        // array of asset keys to be automatically loaded
        let playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: assetKeys)
        
        // Register as an observer of the player item's status property
        self.observer = playerItem.observe(\.status, options:  [.new, .old], changeHandler: { (playerItem, change) in
            if playerItem.status == .readyToPlay {
                //Do your work here
                hideProgressIndicator(view: self.view)
                self.videoThumbNail.isHidden = true
                self.player?.play()
                print("ready")
            }else if playerItem.status == .failed{
                print("failed")
            }else{
                print("unknown")
            }
        })
        
        // Associate the player item with the player
        player = AVPlayer(playerItem: playerItem)
        
        playerLayer = AVPlayerLayer(player: player)
        playerLayer.videoGravity = .resizeAspectFill
        videoView.layer.addSublayer(playerLayer)
        
        //add observer when complete
        NotificationCenter.default
            .addObserver(self,
                         selector: #selector(playerDidFinishPlaying),
                         name: .AVPlayerItemDidPlayToEndTime,
                         object: player?.currentItem
            )
    }
    
    //dismiss Viewcontioller when video is complete 
    @objc func playerDidFinishPlaying(note: NSNotification) {
        print("Video Finished")
        self.dismiss(animated: true)
    }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.