纯血鸿蒙APP实战开发——边缓存边播放案例

介绍

OhosVideoCache是一个支持边播放边缓存的库,只需要将音视频的url传递给OhosVideoCache处理之后再设置给播放器,
OhosVideoCache就可以一边下载音视频数据并保存在本地,一边读取本地缓存返回给播放器,使用者无需进行其他操作。

效果图预览

使用说明

  1. 进入页面,自动播放视频,点击暂停,视频停止播放,点击播放,视频继续播放。
  2. 视频播放完成之后,点击播放按钮,视频重新播放。

实现思路

边缓存播放功能主要是通过Xcomponent组件、@ohos.multimedia.media以及OhosVideoCache三方库实现,XComponent组件主要用于绘制
视频播放的窗口,页面进来初始化服务器然后利用XComponent组件的onLoad函数来调用VideoPlayerManager
中的initPlayer方法创建一个音视频管理实例,并通过setAVPlayerCallback函数和cacheAndPlayVideo函数来实现视频状态的监听以及边缓存边播放功能。

  1. XComponent组件绘制视频播放窗口。源码参考VideoCacheView.ets。
XComponent({
  id: 'xcomponent',
  type: 'surface',
  controller: this.componentController
})
  .height(`${this.xComponentHeight}px`)
  .width(`${this.xComponentWidth}px`)
  .onLoad(() => {
    // 设置XComponent持有Surface的宽度和高度
    this.componentController.setXComponentSurfaceSize({
      surfaceWidth: SURFACE_WIDTH,
      surfaceHeight: SURFACE_HEIGHT
    });
    this.surfaceId = this.componentController.getXComponentSurfaceId();
    // 创建音视频播放实例
    AvPlayManager.getInstance()
      .initPlayer(getContext(this) as common.UIAbilityContext, this.surfaceId, (avPlayer: media.AVPlayer) => {
        avPlayer.on('timeUpdate', (time: number) => {
          this.currentTime = time;
        });
        this.videoDuration = handleTime(avPlayer.duration);
        this.total = avPlayer.duration;
      })
  })
  1. 初始化代理服务器,页面一进来需要使用setServer方法来初始化代理服务器,以便后续调用此服务器处理url。源码参考GlobalProxyServer.ets
import common from '@ohos.app.ability.common';
import { HttpProxyCacheServer } from '@ohos/video-cache';

const CONTEXT_STR: string = 'context';
const SERVER_STR: string = 'server';

export default class GlobalProxyServer {
  private static instance: GlobalProxyServer | null = null;
  private objects: Map<string, Object | null> = new Map<string, Object | null>();

  public static getInstance(): GlobalProxyServer {
    if (!GlobalProxyServer.instance) {
      GlobalProxyServer.instance = new GlobalProxyServer();
    }
    return GlobalProxyServer.instance;
  }
  /**
   * 获取上下文信息
   * @returns
   */
  getContext(): common.UIAbilityContext {
    return this.objects.get(CONTEXT_STR) as common.UIAbilityContext;
  }
  /**
   * 设置上下文信息
   * @param context
   */
  setContext(context: common.UIAbilityContext): void {
    this.objects.set(CONTEXT_STR, context);
  }

  /**
   * 获取服务器
   * @returns
   */
  getServer(): HttpProxyCacheServer {
    return this.objects.get(SERVER_STR) as HttpProxyCacheServer;
  }

  /**
   * 设置服务器
   * @param objectClass
   */
  setServer(objectClass: HttpProxyCacheServer): void {
    try {
      const currentServer: HttpProxyCacheServer = this.getServer();
      currentServer.shutdown();
    } catch (err) {
    }
    this.objects.set(SERVER_STR, objectClass);
  }
}
  1. media.createAVPlayer()创建播放管理类,用于管理和播放媒体资源。源码参考VideoPlayerManager.ets
  async initPlayer(context: common.UIAbilityContext, surfaceId: string,
                   callback: (avPlayer: media.AVPlayer) => void): Promise<void> {
    logger.info(TAG, `initPlayer==initCamera surfaceId== ${surfaceId}`);
    this.surfaceID = surfaceId;
    try {
      // 创建avPlayer实例对象
      this.avPlayer = await media.createAVPlayer();
      // 创建状态机变化回调函数
      await this.setAVPlayerCallback(callback);
      // 边缓存边播放
      this.cacheAndPlayVideo(context);
    } catch (err) {
      logger.error(TAG, `initPlayer initPlayer err:${JSON.stringify(err)}`);
    }
  }
  1. 边播放边缓存,MyCacheListener监听缓存进度,getProxyUrl(ORIGIN_URL)获取视频播放地址并设置给播放器。源码参考VideoPlayerManager.ets
 /**
   * 边缓存边监听函数
   * @param context 上下文信息
   * @returns
   */
  async cacheAndPlayVideo(context: common.UIAbilityContext): Promise<void> {
    logger.info(TAG, `cacheAndPlayVideo start`);

    // TODO:知识点:监听缓存进度
    class MyCacheListener implements CacheListener {
      onCacheAvailable(cacheFilePath: string, url: string, percentsAvailable: number): void {
        AppStorage.setOrCreate('currentCachePercent', percentsAvailable);
      }
    }

    GlobalProxyServer?.getInstance()?.getServer()?.registerCacheListener(new MyCacheListener(), ORIGIN_URL);
    // TODO:知识点:将原始的音视频url交给OhosVideoCache
    let proxyUrl: string | undefined = await GlobalProxyServer?.getInstance()?.getServer()?.getProxyUrl(ORIGIN_URL);
    // 由于avplayer不支持直接加载本地文件路径 这里需要转化为fd的路径
    if (proxyUrl.startsWith(context.cacheDir)) {
      const file = fs.openSync(proxyUrl, fs.OpenMode.READ_ONLY);
      proxyUrl = `fd://${file.fd}`;
    }
    logger.info(TAG, `proxyUrl ${proxyUrl}`);
    // 将处理之后的url设置给播放器
    this.avPlayer.url = proxyUrl;
  }

高性能知识点

不涉及。

工程结构&模块类型

videocache                                         // har类型
|---model
|   |---GlobalProxyServer.ets                      // 模型层-服务器管理
|   |---VideoPlayerManager.ets                     // 模型层-音视频管理
|---utils
|   |---utils.ets                                  // 工具
|---view
|   |---VideoCacheView.ets                         // 视图层-应用主页面

模块依赖

本实例依赖common模块来实现日志的打印、资源
的调用、动态路由模块来实现页面的动态加载以及video-cache,版本为1.0.0。

参考资料

音视频管理

鸿蒙全栈开发全新学习指南

为了让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包含了大厂APP实战项目开发】

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

低耦合双写一致性方案-使用canal+MQ

需求&#xff1a;继上一篇使用xxljob实现数据的全量同步到es后&#xff0c;当数据库中新增、删除、修改数据时&#xff0c;应该对es中的对应索引库实现增量同步。 本文介绍了2种双写一致性方案&#xff0c;对其中使用MQ的方案进行了实现。 1. 方案设计 1.1 数据一致性问题分析…

vue 点击复制文本到剪贴板

一、首先在vue文件的template中定义复制按钮 <div size"small" v-if"item.prop jadeCode" class"cell-container"><span>{{ scope.row.jadeCode }}</span> <button click"handleCopy(scope.row.jadeCode)" clas…

js——数据操作——实现阶梯价格排序——基础积累

最近在写网络报价的时候&#xff0c;遇到一个需求&#xff0c;就是要根据采购数量&#xff0c;找到符合数量的阶梯区间&#xff0c;并找到最便宜的采购价格。 比如下面&#xff1a; let originViewList [{id:1,incrementalQuantity:10,priceList:[{minQuantity:1,price:20},…

el-upload上传图片,视频可获取视频时长。

对element-ui组件的upload组件再一次封装&#xff0c;简单记录。下面是效果图。 注意点&#xff1a;该组件现在仅支持单图和单个视频上传。 <template><div :style"myStyle"><divclass"uploads":style"{width: upWith px,height: up…

零门槛微调大模型:基于 Ludwig 低代码框架使用 LoRA 技术微调实践

一、Ludwig 介绍 自然语言处理 (NLP) 和人工智能 (AI) 的飞速发展催生了许多强大的模型&#xff0c;它们能够理解和生成如同人类般的文本&#xff0c;为聊天机器人、文档摘要等应用领域带来了革命性的改变。然而&#xff0c;释放这些模型的全部潜力需要针对特定用例进行微调。…

我用通义千问做了个银从初级法规考试答题AI助手

我用通义千问做了个银从初级法规考试答题AI助手 起因方法&#xff1a;创建方法&#xff1a;微调成果展示 起因 多选考试实在太难了&#xff0c;惨不忍睹的正确率&#xff0c;博主我就想有一个专门刷多选的工具&#xff0c;但找了半天没找到。然后就想到用通义试试&#xff0c;…

MySQL 服务无法启动

常见原因: 检查端口占用&#xff1a; 使用命令行工具&#xff08;如netstat&#xff09;来检查3306端口是否已被其他程序占用,输入netstat -ano&#xff08;Windows&#xff09;或netstat -tulnp | grep 3306&#xff08;Linux/Mac&#xff09;来查找3306端口的占用情况。如果…

excel转pdf并且加水印,利用ByteArrayOutputStream内存流不产生中间文件

首先先引入包&#xff1a;加水印和excel转PDF的 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.12</version></dependency><dependency><groupId>org.apache.poi&l…

【Numpy】深入解析numpy.diag()函数

numpy.diag()&#xff1a;深入探索NumPy库中的对角矩阵操作 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f3…

统计绘图:基于matplotlib包绘制双轴图

本文介绍通过 Python的matplotlib包 绘制 双轴图&#xff08;Dual Y-Axis Plot&#xff09;&#xff0c;即双 y 轴图&#xff0c;又称双纵坐标图。 这类图表的主要用途是显示两个具有不同数值范围的变量在同一 x 轴上的 变化趋势&#xff0c;从而便于比较和分析。&#xff08;…

docker中安装jenkins,并在node和cloud上跑通基于源码控制SCM的pipeline

目录 一、摘要 二、部署和使用 1. docker部署jenkins 1.1 准备数据目录 1.2 拉取jenkins镜像并启动 1.3 初始化配置 1.3.1 登录容器查看初始化密码 1.3.2 访问jenkins并输入初始化密码 1.3.3 创建管理员账户 1.3.4 初始化完成 2. jenkins使用之多分支流水线 2.1 准…

大模型落地竞逐,云计算大厂“百舸争流”

作者 | 辰纹 来源 | 洞见新研社 从ChatGPT到Sora&#xff0c;从图文到视频&#xff0c;从通用大模型到垂直大模型……经过了1年多时间的探索&#xff0c;大模型进入到以落地为先的第二阶段。 行业的躁动与资本的狂热相交汇&#xff0c;既造就了信仰派的脚踏实地&#xff0c;也…

适用于当下的红色系统可视化大屏,大量图。

特定场合下使用红色系可视化大屏是可以的&#xff0c;但是千万要注意时间和场合&#xff0c;平时最好别用。

获取支持Windows7的最新Edge离线版本

从110版本开始&#xff0c;微软Edge和谷歌停止了对Win7、Win8/8.1的支持&#xff0c;后续又发布了几版安全更新&#xff0c;截止目前为止&#xff0c;能支持Win7的版本是 109.0.1518.140。 如果你想用最新版本谷歌浏览器&#xff0c;可以考虑下Supermium&#xff0c;这个浏览器…

内存马实战(持续更新中)

注&#xff1a;这篇文章记录在我的语雀里面&#xff0c;语雀格式好看一点&#xff0c;地址&#xff1a; https://ganmaocai.yuque.com/ghgp8x/zoy1yn/faet35ae9gpxzn61 计划 复现以下框架的内存马注入&#xff1a; shiro&#xff1a; 普通内存马 冰蝎马 WebSocket马 xxl-job…

C++ 计时器

文章目录 一、简介二、实现代码2.1 windows平台2.2 C标准库 三、实现效果 一、简介 有时候总是会用到一些计时的操作&#xff0c;这里也整理了一些代码&#xff0c;包括C标准库以及window自带的时间计算函数。 二、实现代码 2.1 windows平台 StopWatch.h #ifndef STOP_WATCH_H…

JWT的详解

一.什么是JWT JWT&#xff08;JSON Web Token&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络应用间安全地传递信息。它是一种紧凑的、自包含的方式&#xff0c;用于在用户和服务之间以 JSON 对象的形式安全地传输信息。 JWT 主要由三部分…

计算机系统基础 7 分支程序的实现

简单条件转移指令 根据单个标志位的值&#xff08;CF&#xff0c; SF&#xff0c;OF&#xff0c;PF&#xff0c;ZF&#xff09;来确定是否转移&#xff0c; 如果条件成立&#xff0c;则&#xff08;EIP&#xff09; 位移量 ➡ EIP&#xff0c;否则什么也不做。 注意&#xff0…

c# 将数据库连接字符串写到配置文件中,及获取

考虑到代码的安全性&#xff0c;已经修改起来的方便性&#xff0c;我们常常不会将数据库连接字符串直接放在代码中&#xff0c;而是将这个字符串放到一个App.config配置文件中&#xff0c;赋值给一个变量&#xff0c;然后再在代码中引用这个变量。 具体做法如下: ①展开项目名称…

微星笔记本618爆款推荐清单,好评有礼活动火热进行中

微星笔记本618爆款推荐清单&#xff0c;好评有礼活动火热进行中 又是一年一度的618大促&#xff0c;作为电子数码产品的主场&#xff0c;准备选购笔记本的消费者早已翘首以盼有更实惠的价格~ 不负期待&#xff0c;微星笔记本携多款性价比爆款笔记本、Claw掌上游戏机&#xff0…