iOS 视频播放器开发

news2024/11/16 4:15:04

需求设计

做一个小学生教育辅导视频播放器。

参考小猿搜题视频播放器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0GsyFSt-1675164972791)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZ7e0Z3Z-1675164972792)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)]

主要功能

  • 非VIP用户免费播放开头部分;
  • 截屏;
  • 倍速播放;
  • 进度条快进快退;

实现原理

  1. 公开属性
#import "WMPlayer.h"
@property (nonatomic, retain) WMPlayerModel *playerModel;
@property (nonatomic, strong) WMPlayer  *wmPlayer;
  1. 实例化播放器
    //self.wmPlayer = [[WMPlayer alloc] initWithFrame:CGRectMake(0, [WMPlayer IsiPhoneX]?34:0, self.view.frame.size.width, self.view.frame.size.width*(9.0/16))];
    self.wmPlayer = [[WMPlayer alloc] initWithFrame:CGRectMake(0, 44, self.view.frame.size.width, self.view.frame.size.height-88)];
    self.wmPlayer.delegate = self;
    self.wmPlayer.playerModel = self.playerModel;
    [self.view addSubview:self.wmPlayer];
    [self.wmPlayer play];
    
    //旋转屏幕通知
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(onDeviceOrientationChange:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];

  1. VC生命周期
#pragma mark - Life Cycle

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:YES animated:NO];
    self.view.frame = UIScreen.mainScreen.bounds;
    self.wmPlayer.delegate = self;
}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

- (void)dealloc{
    [self.wmPlayer pause];
    [self.wmPlayer removeFromSuperview];
    self.wmPlayer = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    NSLog(@"DetailViewController dealloc");
}
  1. 播放器代理
#pragma mark - WMPlayerDelegate
///播放器CloseButton
-(void)wmplayer:(WMPlayer *)wmplayer clickedCloseButton:(UIButton *)closeBtn{
    if (wmplayer.isFullscreen) {
        [self exitFullScreen];
    }else{
        if (self.presentingViewController) {
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }else{
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
}
///全屏按钮
-(void)wmplayer:(WMPlayer *)wmplayer clickedFullScreenButton:(UIButton *)fullScreenBtn{
    if (self.wmPlayer.viewState == PlayerViewStateSmall) {
         [self enterFullScreen];
    }
}

-(void)enterFullScreen{
    if (self.wmPlayer.viewState != PlayerViewStateSmall) {
        return;
    }
    LandscapeRightViewController *rightVC = [[LandscapeRightViewController alloc] init];
    [self presentToVC:rightVC];
}

-(void)exitFullScreen{
    if (self.wmPlayer.viewState!=PlayerViewStateFullScreen) {
        return;
    }
    self.wmPlayer.isFullscreen = NO;
    self.wmPlayer.viewState = PlayerViewStateAnimating;
    [self dismissViewControllerAnimated:YES completion:^{
        self.wmPlayer.viewState  = PlayerViewStateSmall;
    }];
}
  1. 旋转屏幕通知
#pragma mark - NSNotificationCenter
/**
 *  旋转屏幕通知
 */
- (void)onDeviceOrientationChange:(NSNotification *)notification{
    if (self.wmPlayer.viewState!=PlayerViewStateSmall) {
        return;
    }
    if (self.wmPlayer.isLockScreen){
        return;
    }
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)orientation;
    switch (interfaceOrientation) {
        case UIInterfaceOrientationPortraitUpsideDown:{
        }
            break;
        case UIInterfaceOrientationPortrait:{

        }
            break;
        case UIInterfaceOrientationLandscapeLeft:{
            [self presentToVC:[LandscapeLeftViewController new]];
        }
            break;
        case UIInterfaceOrientationLandscapeRight:{
            [self presentToVC:[LandscapeRightViewController new]];
        }
            break;
        default:
            break;
    }
}

-(void)presentToVC:(FullScreenHelperViewController *)aHelperVC{
    self.wmPlayer.viewState = PlayerViewStateAnimating;
    self.wmPlayer.beforeBounds = self.wmPlayer.bounds;
    self.wmPlayer.beforeCenter = self.wmPlayer.center;
    self.wmPlayer.parentView = self.wmPlayer.superview;
    self.wmPlayer.isFullscreen = YES;
    aHelperVC.wmPlayer = self.wmPlayer;
    aHelperVC.modalPresentationStyle = UIModalPresentationFullScreen;
    aHelperVC.transitioningDelegate = self;
    [self presentViewController:aHelperVC animated:YES completion:^{
        self.wmPlayer.viewState = PlayerViewStateFullScreen;
    }];
}
  1. 调用播放器
        VideoDataModel *videoModel = self.videoDataAry[indexPath.row];
        WMPlayerModel *playerModel = [WMPlayerModel new];
        playerModel.videoURL = [NSURL URLWithString:videoModel.video_url];
        //playerModel.videoURL = [NSURL URLWithString:@"http://static.tripbe.com/videofiles/20121214/9533522808.f4v.mp4"];
        //playerModel.videoURL = [NSURL URLWithString:@"http://img.zhuoqi.tech/test_h264_level30_480_360.mp4"];
        playerModel.title = videoModel.nickname;
        DetailViewController *detailVC = [DetailViewController new];
        detailVC.playerModel = playerModel;
        [self.navigationController pushViewController:detailVC animated:YES];

基本概念

一个在线视频能够播放,大致是经过了如下步骤:

视频播放原理

HLS(Http Live Streaming)

HLS是苹果推出,实现的基于HTTP的流媒体传输协议:

优点:

1、通过m3u8索引文件可实现针对当前浏览设备的智能选择播放源

2、通过m3u8索引文件可实现添加备份索引文件,防止服务器崩溃视频播放失败

3、和http视频一样不需要太多服务器额外配置

缺点:

1、并非真正实时视频,30s左右时间差

2、需要视频处理

3、因为需要请求索引文件(ts视频文件)请求次数相对较多,对服务器负载较大

AVPlayer支持哪些视频格式

苹果设备支持音视频格式并不是就代表AVPlayer也支持那么多格式,确定AVPlayer的支持格式,我们可以查看AVKit中的一个API:

//展示当前支持的音视频格式
let asset = AVURLAsset.audiovisualTypes()
//打印asset可以得到(已经转过展示格式)
asset type (
    "audio/aacp",
    "video/3gpp2",
    "audio/mpeg3",
    "audio/mp3",
    "audio/x-caf",
    "audio/mpeg",
    "video/quicktime",
    "audio/x-mpeg3",
    "video/mp4",
    "audio/wav",
    "video/avi",
    "audio/scpls",
    "audio/mp4",
    "audio/x-mpg",
    "video/x-m4v",
    "audio/x-wav",
    "audio/x-aiff",
    "application/vnd.apple.mpegurl",
    "video/3gpp",
    "text/vtt",
    "audio/x-mpeg",
    "audio/wave",
    "audio/x-m4r",
    "audio/x-mp3",
    "audio/AMR",
    "audio/aiff",
    "audio/3gpp2",
    "audio/aac",
    "audio/mpg",
    "audio/mpegurl",
    "audio/x-m4b",
    "application/mp4",
    "audio/x-m4p",
    "audio/x-scpls",
    "audio/x-mpegurl",
    "audio/x-aac",
    "audio/3gpp",
    "audio/basic",
    "audio/x-m4a",
    "application/x-mpegurl"
)

AVPlayer支持的

视频编码格式:H.264、HEVC(iPhone7及以后设备)、MPEG-4。
视频封装格式:.mp4、.mov、.m4v、.3gp、.avi等。
如果想支持更多的视频格式,可以使用使用第三方的框架,常用的视频编码和解码框架有VLC和ffmpeg。

AVPlayerItem的控制

AVPlayerItem作为资源管理对象,它控制着视频从创建到销毁的诸多状态。

播放状态 status

typedef NS_ENUM(NSInteger,AVPlayerItemStatus) {
        AVPlayerItemStatusUnknown,//未知
        AVPlayerItemStatusReadyToPlay,//准备播放
        AVPlayerItemStatusFailed//播放失败
};

我们使用KVO监测playItem.status,可以获取播放状态的变化

[self.playerItem addObserver:selfforKeyPath:@"status"options:NSKeyValueObservingOptionNewcontext:nil];

在监听回调中:

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context{
    if([object isKindOfClass:[AVPlayerItemclass]]) {
        if([keyPath isEqualToString:@"status"]) {
            switch(_playerItem.status) {
                caseAVPlayerItemStatusReadyToPlay://推荐将视频播放放这里
                    [self play];
                    break;
                caseAVPlayerItemStatusUnknown:
                    NSLog(@"AVPlayerItemStatusUnknown");
                    break;
                caseAVPlayerItemStatusFailed:
                    NSLog(@"AVPlayerItemStatusFailed");
                    break;
                default:
                    break;
             }
        }
    }
}

虽然设置完播放配置我们可以直接调用[self.player play];进行播放,但是更稳妥的方法是在回调收到AVPlayerItemStatusReadyToPlay时进行播放。

参考文章

HTTP Streaming Architecture

HTTP Live Streaming

WMPlayer

WeChat

SJVideoPlayer

DouYin

TBPlayer

iOS视频播放器开发

iOS视频播放的基本方法

上传到阿里云OSS的视频如何实现在线播放

ZFPlayer 3.0解析

AVPlayer支持的视频格式

iOS音视频播放指南(一)

iOS音视频开发学习指南

iOS视频开发(一):视频采集

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/190249.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中的JCA对基于密码的加密进行成功的蛮力搜索攻击所需的时间估计

对于JCA中基于密码的DES加密实现,固定一些盐和迭代计数,并记录加密/解密所需的平均时间;估计成功进行蛮力搜索攻击所需的时间Name: NIHAO DONG Number: 201476606 Password List:N Password 1 P$$W0rD 2 thisismypassword 3 VeryLongP$$W0rD fi…

[0CTF 2016]piapiapia(字符逃逸详解)

目录 知识点 信息收集 尝试SQL注入 源码目录扫描 代码审计 payload生成 知识点 信息泄露参数传递数组绕过字符串检测反序列化字符逃逸 信息收集 收集到了一只超可爱的小喵 尝试SQL注入 用户名不存在的回显 密码无效的回显 用户存在,密码错误的回显 判断闭…

STC15系列PWM功能相关功能寄存器介绍

STC15系列PWM功能相关功能寄存器介绍✨以下数据来源于stc15手册。 📓增强型PWM波形发生器相关功能寄存器总表 1. 端口配置寄存器:P_SW2 2.PWM配青寄存器:PWMICFG CBTADC: PWM计数器归零时 (CBIF1时) 触发ADC转换 – 0:PWM计数器归零时不触发ADC转换 – …

Web3中文|亚马逊进入web3,将在春季推出NFT计划

亚马逊正向加密行业迈出第一步。 根据Blockworks 1月26日发布的报告,这家电子商务巨头计划在2023年春天推出一项专注于区块链游戏和相关NFT的计划。 该计划仍处于开发阶段,但发布的最后期限定为4月。亚马逊用户将可以体验基于区块链的游戏并领取免费的…

Python采集某乎专栏文章保存成pdf

前言 大家早好、午好、晚好吖 ❤ ~ 环境使用: Python 3.8 Pycharm wkhtmltopdf 软件 --> 文章下方名片信领取 模块使用: requests >>> pip install requests 数据请求 parsel >>> pip install parsel 数据解析 re >>> 内置模块 不需要安装…

域内委派攻击

域委派是指,将域内用户的权限委派给服务账号,使得服务账号能以用户权限开展域内活动。利用委派可获取域管理员权限 域委派主要分为三种: 非约束性委派 约束性委派 基于资源的约束性委派 在Windows系统中,只有服务账号和主机账号…

操作系统权限提升(五)之系统错误配置-PATH环境变量提权

系列文章 操作系统权限提升(一)之操作系统权限介绍 操作系统权限提升(二)之常见提权的环境介绍 操作系统权限提升(三)之Windows系统内核溢出漏洞提权 操作系统权限提升(四)之系统错误配置-Tusted Service Paths提权 注:阅读本编文章前,请先阅读系列文章…

寻找整数

问题描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 有一个不超过 10^{17}1017 的正整数 nn,知道这个数除以 2 至 49 后的余数如下表所示,求这个正整数最小是多少。 运行限制 最大运行时间:1s最大运行内存: 512M参考答案 mp = {2: 1, …

虹科动态 | 虹科HSR/PRP IP核现已支持HSR/PRP最新标准

HSR与PRP是专注于解决高可靠性自动化网络传输的技术,其所属的国际标准为IEC 62439。最初,IEC发布此项标准主要目的是为了满足IEC 61850-5中所提到的变电站自动化应用中各通信组件或服务故障所要求的恢复时间问题,但协议设计时的通用性&#x…

PTA L1-017 到底有多二

前言:本期是关于到底有多二的详解,内容包括四大模块:题目,代码实现,大致思路,代码解读,今天你c了吗? 题目: 一个整数“犯二的程度”定义为该数字中包含2的个数与其位数…

Java多线程:Future和FutureTask

一、Future Future是一个接口&#xff0c;所有方法如下&#xff1a; 上源码&#xff1a; package java.util.concurrent; public interface Future<V> {boolean cancel(boolean mayInterruptIfRunning);boolean isCancelled();boolean isDone();V get() throws Interru…

5.3 场效应管的高频等效模型

由于场效应管各级之间存在极间电容&#xff0c;因而其高频响应与晶体管相似。根据场效应管的结构&#xff0c;可得出图5.3.1(a)所示的高频等效模型&#xff0c;大多数场效应管的参数如表1所示。由于一般情况下 rgsr_{gs}rgs​ 和 rdsr_{ds}rds​ 比外接电阻大得多&#xff0c;因…

Lesson 4.5 梯度下降优化基础:数据归一化与学习率调度

文章目录一、数据归一化方法1. 数据归一化计算公式1.1 0-1 标准化1.2 Z-Score 标准化1.3 非线性标准化2. 数据归一化算法执行过程3. 数据归一化算法评价4. Z-Score 标准化算法评价及横向对比二、梯度下降算法优化初阶1. 数据归一化与梯度下降算法优化2. 学习率调度3. 小批量梯度…

RV1126笔记二十六:lvgl移植

若该文为原创文章,转载请注明原文出处。 之前做项目的时候有了解到LVGL这个开源的gui库,有QT仿真过智能家居控制界面,也在STM32上移植过。 趁着过年期间就想着把它移植到自己的开发板上看看能不能正常跑起来。虽说不难,但也花了一些功夫,因此也在这里做下总结。 下载地址…

STC15系列PWM中断控制寄存器介绍以及PWM相关示例

STC15系列PWM中断控制寄存器介绍以及PWM呼吸灯代码实现&#x1f4cc;相关篇《STC15系列PWM功能相关功能寄存器介绍》✨以下数据来源于stc15手册。 &#x1f4d3;增强型PWM波形发生器的中断控制 1.PWM中断优先级控制寄存器:IP2 PPWMFD:PWM异常检测中断优先级控制位。 当PPWMFD…

微信小程序员010宠物交易系统商城系统

宠物交易系统商城系统分为用户小程序端和管理员后台网页端&#xff0c;其中后端是采用java编程语言&#xff0c;mysql数据库&#xff0c;idea开发工具&#xff0c;ssm框架开发&#xff0c;本系统分为用户和管理员两个端&#xff0c;其中用户可以在小程序端进行注册登陆&#xf…

嵌入式Linux从入门到精通之第十节:系统编程之进程

进程的定义 程序:程序是存放在存储介质上的一个可执行文件。进程:进程是程序的执行实例,包括程序计数器、寄存器和变量的当前值。程序是静态的,进程是动态的: 程序是一些指令的有序集合,而进程是程序执行的过程。进程的状态是变化的,其包括进程的创建、调度和消亡。 在…

【微服务】分布式搜索引擎elasticsearch(1)

分布式搜索引擎elasticsearch&#xff08;1&#xff09;1.elasticsearch1.1.了解ES1.1.1.elasticsearch的作用1.1.2.ELK技术栈1.1.3.elasticsearch和lucene1.1.4.为什么不是其他搜索技术&#xff1f;1.1.5.总结1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排1.3.es…

08-linux网络管理-nc命令(TCP|UDP网络联通测试,文件传输,带宽测试)

文章目录1. 安装2. 选项2.1 帮助命令2.2 常用示例- 监听TCP端口&#xff08;默认&#xff09;- 监听UDP端口- 链接TCP端口- 链接UDP端口- 接收数据重定向- 上传数据3. 完整示例3.1 示例1&#xff08;端口联通检查&#xff09;3.2 示例2&#xff08;文件传输&#xff09;3.3 带宽…

Linux权限的基本知识

本文已收录至《Linux知识与编程》专栏&#xff01;作者&#xff1a;ARMCSKGT演示环境&#xff1a;CentOS 7 目录 前言 正文 权限是什么&#xff1f; Linux权限的划分 Linux用户的切换命令 Linux文件权限 Linux文件类型 Linux文件权限 Linux角色划分 文件权限的访问和…