美文网首页ios第三方资源iOS学习iOS视屏
6.4 视频->1.0 视频播放方案

6.4 视频->1.0 视频播放方案

作者: 蓝田_Loto | 来源:发表于2016-10-12 15:34 被阅读250次

本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。


本文相关目录:
===================== 所属文集:6.0 图形和多媒体 =====================
6.1 Quartz 2D->1.1 Quartz 2D 简介
6.2 核心动画->1.0 CALayer的简介
··················· 1.1 CALayer的基本属性
··················· 1.2 CALayer的创建 & 非根layer的隐式动画
··················· 2.0 Core Animation(核心动画)
··················· 3.0 核心动画 & UIView动画
··················· 4.0 常用动画效果
6.3 音频->1.0 录音 未发布
············· 2.0 音效/音乐 未发布
············· iOS项目Demo - 仿·QQ音乐播放器 未发布
6.4 视频->1.0 视频播放方案
············· 2.0 视频特效:画中画
············· 3.0 视频功能
············· iOS项目Demo - 仿·慕课网视频播放器 未发布
6.5 直播 未发布
6.5 直播-> iOS项目Demo - 仿·斗鱼直播 未发布
===================== 所属文集:6.0 图形和多媒体 =====================


视频目录

本文目录


0. 配置plist文件:iOS9.0 网络请求适配 (HTTPS-->HTTP)

关键词:
App Transport Security Settings
Allow Arbitrary Loads


方案1:AVPlayer播放视频

代码1:AVPlayer播放视频 demo

编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0

【OC语言】

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()
@property (nonatomic, strong) AVPlayer *player;
@end

@implementation ViewController

#pragma mark - 懒加载
-(AVPlayer *)player{
    if (!_player) {
        
        // ① 本地媒体文件
        NSString *path = [[NSBundle mainBundle]pathForResource:@"1.mp4" ofType:nil];
        NSURL *url = [NSURL fileURLWithPath:path];
        _player = [AVPlayer playerWithURL:url];
        
        // ② 通过远程URL创建AVPlayer对象
        //  NSURL *remoteURL = [NSURL URLWithString:@"http://v1.mukewang.com/57de8272-38a2-4cae-b734-ac55ab528aa8/L.mp4"];
        //  _player = [AVPlayer playerWithURL:remoteURL];
    }
    return _player;
}

- (void)viewDidLoad{
    // 2.1 根据player对象, 创建 AVPlayerLayer 对象
    AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    
    // 2.2 设置图层 AVPlayerLayer 的大小
    layer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height * 9 / 16);
    
    // 2.3 添加到需要展示的视图上即可
    [self.view.layer addSublayer:layer];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    // 1.2 开始播放
    [self.player play];
}

@end
【Swift 语言】
import UIKit
import AVFoundation

class ViewController: UIViewController {
    
    lazy var player: AVPlayer = {
        
        // ① 本地媒体文件
        let infoPlistPath = Bundle.main.url(forResource: "1", withExtension: "mp4")
        let player = AVPlayer(url: infoPlistPath!)
        
        // ② 通过远程URL创建AVPlayer对象
        // let url = URL(string: "http://v1.mukewang.com/19954d8f-e2c2-4c0a-b8c1-a4c826b5ca8b/L.mp4")
        // let player = AVPlayer(url: url!)
        
        return player
    }()
    
    var layer: AVPlayerLayer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 2.1 根据player对象, 创建 AVPlayerLayer 对象
        layer = AVPlayerLayer(player: self.player)
        
        // 2.3 添加到需要展示的视图上即可
        view.layer.addSublayer(layer!)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 1.2 开始播放
        player.play()
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        // 2.2 设置图层 AVPlayerLayer 的大小
        layer?.frame = view.layer.bounds
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

方案2:MPMoviePlayerController播放视频

代码2:MPMoviePlayerController播放视频 demo

编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0

【OC语言】

#import "ViewController.h"
#import <MediaPlayer/MediaPlayer.h> // 视频播放的框架(已过期)

@interface ViewController ()
@property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
@end

@implementation ViewController

-(MPMoviePlayerController *)moviePlayer{
    if (!_moviePlayer) {
        
        // ① 本地媒体文件
        NSString *path = [[NSBundle mainBundle]pathForResource:@"1.mp4" ofType:nil];
        NSURL *url = [NSURL fileURLWithPath:path];
        _moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
        
        // ② 通过远程URL, 创建控制器 MPMoviePlayerController
        // NSURL *remoteURL = [NSURL URLWithString:@"http://v1.mukewang.com/57de8272-38a2-4cae-b734-ac55ab528aa8/L.mp4"];
        // _moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:remoteURL];
    }
    return _moviePlayer;
}

// 2. 设置播放视图frame, 添加到需要展示的视图上
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 设置播放视图的frame
    self.moviePlayer.view.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height * 9 / 16);
    
    /*
     MPMovieControlStyleNone,       // 不显示控制台(没有播放控制控件)
     MPMovieControlStyleEmbedded,   // 默认(嵌入式播放控件。没有Done按钮)
     MPMovieControlStyleFullscreen  // 显示全部控制台(全屏播放,有播放进度、Done按钮和快进等控件)
     */
    // 设置控制台的样式
    self.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
    
    // 添加播放视图到要显示的视图
    [self.view addSubview:self.moviePlayer.view];
    
    // 注册通知中心 接受通知(MPMoviePlayerPlaybackDidFinishNotification)
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayerPlaybackDidFinish)
                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                               object:nil];
}

// 接收到通知会来到此方法 (效果:切换下一个视频)
- (void)moviePlayerPlaybackDidFinish{
    
    // 创建URL,更换视频
    NSString *path = [[NSBundle mainBundle]pathForResource:@"2.mp4" ofType:nil];
    NSURL *url = [NSURL fileURLWithPath:path];
    
    // 将下一个视频的URL添加到contentURL
    self.moviePlayer.contentURL = url;
    
    // 播放
    [self.moviePlayer play];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    // 3.播放 (此控制器不是视图控制器, 不能弹出)
    [self.moviePlayer play];
}

@end
【Swift 语言】

import UIKit
import MediaPlayer

class ViewController: UIViewController {
    
    // 懒加载创建播放器
    lazy var controller: MPMoviePlayerController = {
        
        // ① 本地媒体文件
        let infoPlistPath = Bundle.main.url(forResource: "1", withExtension: "mp4")
        let controller = MPMoviePlayerController(contentURL: infoPlistPath!)
        
        // ② 通过远程URL创, 创建控制器 MPMoviePlayerController
        // let url = URL(string: "http://v1.mukewang.com/3e35cbb0-c8e5-4827-9614-b5a355259010/L.mp4")
        // let controller = MPMoviePlayerController(contentURL: url!)
        
        // 添加播放视图到要显示的视图
        self.view.addSubview((controller?.view)!)
        return controller!
    }()
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        // 3.播放
        controller.play()
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        // 2. 设置播放视图frame, 添加到需要展示的视图上
        controller.view.frame = view.bounds
    }
}

方案3:MPMoviePlayerViewController播放视频

代码3:MPMoviePlayerViewController播放视频 demo

编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0

【OC语言】
#import "ViewController.h"
#import <MediaPlayer/MediaPlayer.h>

@interface ViewController ()
@property (nonatomic, strong) MPMoviePlayerViewController *playerVC;
@end

@implementation ViewController

-(MPMoviePlayerViewController *)playerVC
{
    if (!_playerVC) {
        // ① 本地媒体文件
        // 方法1:
        NSString *path = [[NSBundle mainBundle]pathForResource:@"1.mp4" ofType:nil];
        NSURL *url = [NSURL fileURLWithPath:path];
        
        // 方法2:
        // NSURL *url = [[NSBundle mainBundle]URLForResource:@"1.mp4" withExtension:nil];
        
        _playerVC = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
        
        
        // ② 通过远程URL, 创建控制器 MPMoviePlayerViewController
        // NSURL *remoteURL = [NSURL URLWithString:@"http://v1.mukewang.com/57de8272-38a2-4cae-b734-ac55ab528aa8/L.mp4"];
        // _playerVC = [[MPMoviePlayerViewController alloc] initWithContentURL:remoteURL];
    }
    return _playerVC;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    // 2. 直接模态弹出该控制器(或者: 设置播放视图frame, 添加到需要展示的视图上)
    [self presentViewController:self.playerVC
                       animated:YES completion:^{
                           // 3. 开始播放
                           [self.playerVC.moviePlayer play];
                       }];
}

@end
【Swift 语言】

import UIKit
import MediaPlayer

class ViewController: UIViewController {
    
    lazy var playerVC: MPMoviePlayerViewController = {
        
        // ① 本地媒体文件
        let infoPlistPath = Bundle.main.url(forResource: "1", withExtension: "mp4")
        let vc = MPMoviePlayerViewController(contentURL: infoPlistPath!)
        
        // ② 通过远程URL, 创建控制器 MPMoviePlayerViewController
        // let url = URL(string: "http://v1.mukewang.com/a45016f4-08d6-4277-abe6-bcfd5244c201/L.mp4")
        // let vc = MPMoviePlayerViewController(contentURL: url!)
        
        return vc!
    }()
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        // 表示已经弹出控制器,则直接return
        if presentedViewController != nil {
            return
        }
        
        // 2. 直接模态弹出该控制器(或者: 设置播放视图frame, 添加到需要展示的视图上)
        present(playerVC, animated: true) {
            // 3. 开始播放
            self.playerVC.moviePlayer.play()
        }
    }
}

方案4:AVPlayerViewController播放视频

代码4:AVPlayerViewController播放视频 demo

编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0

【OC语言】
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <AVKit/AVKit.h>

@interface ViewController ()
@property (nonatomic, strong) AVPlayerViewController *playerVC;
@end

@implementation ViewController

-(AVPlayerViewController *)playerVC
{
    if (!_playerVC) {
        
        // ① 本地媒体文件
        NSString *path = [[NSBundle mainBundle]pathForResource:@"1.mp4" ofType:nil];
        NSURL *url = [NSURL fileURLWithPath:path];
        AVPlayer *player = [AVPlayer playerWithURL:url];
        
        // ② 通过远程URL创建AVPlayer
        //  NSURL *remoteURL = [NSURL URLWithString:@"http://v1.mukewang.com/57de8272-38a2-4cae-b734-ac55ab528aa8/L.mp4"];
        //  AVPlayer *player = [AVPlayer playerWithURL:remoteURL];
        
        // 2.根据AVPlayer, 创建AVPlayerViewController控制器
        _playerVC = [[AVPlayerViewController alloc] init];
        _playerVC.player = player;
        
        // 设置画中画(ipad)
        // _playerVC.allowsPictureInPicturePlayback = YES;
        
    }
    return _playerVC;
}

// 3. 方式1:设置播放视图frame, 添加播放视图到要显示的视图
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 设置播放视图的frame
    self.playerVC.view.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height * 9 / 16);
    
    // 添加播放视图到要显示的视图
    [self.view addSubview:self.playerVC.view];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    if(self.presentedViewController) return;
    
    // 3. 方式2:直接弹出此控制器
    [self presentViewController:self.playerVC animated:YES completion:nil];
    
    // 4.开始播放
    [self.playerVC.player play];
}

@end
【Swift 语言】
import UIKit
import AVKit
import AVFoundation

class ViewController: UIViewController {
    
    lazy var playerVC: AVPlayerViewController = {
        
        // ① 本地媒体文件
        let infoPlistPath = Bundle.main.url(forResource: "1.mp4", withExtension:nil)
        let player = AVPlayer(url: infoPlistPath!)
        
        // ② 通过远程URL创建AVPlayer
        // let url = URL(string: "http://v1.mukewang.com/3e35cbb0-c8e5-4827-9614-b5a355259010/L.mp4")
        // let player = AVPlayer(url: url!)
        
        // 2.根据AVPlayer, 创建AVPlayerViewController控制器
        let playerVC = AVPlayerViewController()
        playerVC.player = player
        
        // 设置画中画(ipad)
        // playerVC.allowsPictureInPicturePlayback = true
        
        return playerVC
    }()
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        if presentedViewController != nil {
            return
        }
        
        // 3.直接弹出此控制器
        present(playerVC, animated: true) {
            // 4.开始播放
            self.playerVC.player?.play()
        }
    }
}

方案5:第三方框架Vitamio播放视频


注:官网:https://www.vitamio.org

下面详细介绍下使用步骤:

0 . 导入 Vitamio SDK路径:Vitamio-iOS-4.2.6/Vitamio
1 . 配置Target链接参数:选择 Project->Build Settings->Linking->Other Linker Flags, 将该选项的键配置为 -ObjC
2 . 添加系统依赖库:选择Targets->Build Phases->Link Binary With Libraries,添加框架和库


代码5:第三方框架Vitamio播放视频 demo

编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0

【OC语言】 (暂无,后期补上)

【Swift 语言】
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var videoPlayerView: UIView!  // 播放视频的view
    
    // 使用类 VMediaPlayer 的类方法 +sharedInstance 获取播放器共享实例
    let mMPlayer = VMediaPlayer.sharedInstance()
    
    // MARK: - 播放本地视频
    @IBAction func playVideo(_ sender: UIButton) {
        // 设置播放器, 在哪个视图里面显示
        mMPlayer?.setupPlayer(withCarrierView: videoPlayerView, with: self)
        
        // 设置数据源,给播放器传入要播放的视频URL, 并告知其进行播放准备
        // ①本地媒体文件
        let infoPlistPath = Bundle.main.url(forResource: "1", withExtension: "mp4")
        mMPlayer?.setDataSource(infoPlistPath!)
        
        // 准备加载资源
        mMPlayer?.prepareAsync()
    }
    
    // MARK: - 播放网络视频
    @IBAction func play(_ sender: UIButton) {
        // 设置播放器, 在哪个视图里面显示
        mMPlayer?.setupPlayer(withCarrierView: videoPlayerView, with: self)
        
        // 设置数据源,给播放器传入要播放的视频URL, 并告知其进行播放准备
        // ② 网络视频流地址
        let url = URL(string: "http://v1.mukewang.com/3e35cbb0-c8e5-4827-9614-b5a355259010/L.mp4")
        mMPlayer?.setDataSource(url!)
        
        // 准备加载资源
        mMPlayer?.prepareAsync()
    }
    
    // MARK: - 继续播放
    @IBAction func resumPlay(_ sender: UIButton) {
        mMPlayer?.start()
    }
    
    // MARK: - 暂停
    @IBAction func pause(_ sender: UIButton) {
        mMPlayer?.pause()
    }
    
    // MARK: - 停止
    @IBAction func stop(_ sender: UIButton) {
        mMPlayer?.reset()          // 重置
        mMPlayer?.unSetupPlayer()  // 取消注册播放器
    }
    
    // MARK: - 播放到指定时间
    @IBAction func valueChange(_ sender: UISlider) {
        // 拿到视频总时长(getDuration)
        let time = Int(sender.value * Float((mMPlayer?.getDuration())!))
        
        mMPlayer?.seek(to: time)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

// MARK: - 实现 VMediaPlayerDelegate 协议, 以获得'播放器准备完成'等通知
// 下面3个代理必须实现
extension ViewController: VMediaPlayerDelegate {
    
    // 当'播放器准备完成'时, 该协议方法被调用, 我们可以在此调用 [player start] 来开始音视频的播放.
    func mediaPlayer(_ player: VMediaPlayer!, didPrepared arg: Any!) {
        player.start()
        print("播放器准备完成")
    }
    
    // 当'该音视频播放完毕'时, 该协议方法被调用, 我们可以在此作一些播放器善后操作, 如: 重置播放器, 准备播放下一个音视频等
    func mediaPlayer(_ player: VMediaPlayer!, playbackComplete arg: Any!) {
        player.reset()
        print("该音视频播放完毕")
    }
    
    // 如果播放由于某某原因发生了错误, 导致无法正常播放, 该协议方法被调用, 参数 arg 包含了错误原因.
    func mediaPlayer(_ player: VMediaPlayer!, error arg: Any!) {
        print("播放器发生错误")
    }
}

运行效果:



本文源码 Demo 详见 Github(方便的话,帮忙点个Star,谢啦!)
https://github.com/shorfng/iOS_6.0_Graphics_and_multimedia.git



作者:蓝田(Loto)
出处: 简书

如果你觉得本篇文章对你有所帮助,请点击文章末尾下方“喜欢”
如有疑问,请通过以下方式交流:
评论区回复微信(加好友请注明“简书+称呼”)发送邮件shorfng@126.com



本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

相关文章

网友评论

  • way菜畦:评论会影响置顶吗?我也在找怎么在自己主页中将文章置顶啊
    蓝田_Loto:@way菜畦 不是,,,,排布顺序是按照发布日期来的,我的意思是,比如现在这个是文1,我会发布文2,文2在文1的上面。我把文1的内容放在文2里,文1的内容变成我准备写的博客
    way菜畦:@蓝田_Loto 明白你的意思,每次你发其他新文章后,会把这篇重新发布一次。就实现手动置顶?咦,我试了一下貌似不行
    蓝田_Loto:@way菜畦 评论不会影响,只不过,等我发文的时候,现在这篇文章就会变成我要发的文章,我会再重新发布一个新的,最新才会置顶。。。。。我感觉你还是不一定能看得懂我在说什么。-。-
  • 西门欥雪:真详细。
    蓝田_Loto:@冷如冰寒如雪_西门吹雪 感谢支持! :smile:

本文标题:6.4 视频->1.0 视频播放方案

本文链接:https://www.haomeiwen.com/subject/xryiyttx.html