Skip to content
On this page

这篇文章有点不一样的地方,是记录一次公司的一次技术调研与推进。全程由个人主导,先说需求,需求是在支付宝小程序环境内,实现 rtmp 流媒体格式的实时拉流,应用内接到推流的地址,然后进行实时拉流,一句话概括:支付宝小程序用户:能够在小程序内进行观看直播操作。我需要制定一个需求的技术方案。以及这种方式是否可行。这是在2022年6月初的一次前端技术的调研。

背景

先从代码角度出发,项目是 uni-app 的代码,产出的内容是 支付宝小程序,运行在支付宝小程序中 再从产品的角度考虑,当然产品不关心代码具体怎么实现,能够实现心跳检测、结束直播、播放器的全屏与否等等

我要做的就是出一个结论,能不能做,怎么做

一些术语的解释

1、 uni-appuni-app 是前端能够实现跨端的一个框架:例如可以开发支付宝小程序、微信小程序、甚至 APP

2、原生支付宝小程序 完全符合支付宝小程序的一套开发方式:指的通过支付宝自身提供的 API 来进行支付宝小程序的开发

3、实时音视频直播(实时音视频播放):不同于一个简单的视频播放,音视频直播也就直播拉流,对应的也有直播推流。简言之,就是有一个推流端产生一个流地址 例如: rtmp://xxxx 然后支付宝小程序对流进行实时拉取播放

4、文件格式

我在刚毕业的时候做过视频播放相关的项目,对视频的文件格式 有一些基础的了解

文件格式格式的介绍
M3U8M3U8 文件是指 UTF-8 编码格式的 M3U 文件。M3U 文件是记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。M3U 是一种播放多媒体列表的文件格式,它的设计初衷是为了播放音频文件,比如 MP3,但是越来越多的软件现在用来播放视频文件列表,M3U 也可以指定在线流媒体音频源。很多播放器和软件都支持 M3U 文件格式。
MP4MP4 或称 MPEG-4 第 14 部分(英语:MPEG-4 Part 14)是一种标准的数字多媒体容器格式。MPEG-4 第 14 部分的扩展名为.mp4,以存储数字音频及数字视频为主,但也可以存储字幕和静止图像。因其可容纳支持比特流的視频流(如高级視频编码),MP4 可以在网络传输时使用流式传输。虽然携带式媒体播放器有时会被称作"MP4 播放器",但并不仅限于播放 MP4 格式的影片,有些也可以播放 AMV、MKV 或其他影帧式扩展名为.flv 或.f4v 并同样基于 ISO 基础媒体文件格式(MPEG-4 第 12 部分)的 Flash 視频格式与 MPEG-4 第 14 部分极为相似,多数情况下直接变更扩展名为.mp4 也能够正常播放
RTMPRTMP 是 Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于 TCP,是一个协议族,包括 RTMP 基本协议及 RTMPT/RTMPS/RTMPE 等多种变种。RTMP 是一种设计用来进行实时数据通信的网络协议,主要用来在 Flash/AIR 平台和支持 RTMP 协议的流媒体/交互服务器之间进行音视频和数据通信。支持该协议的软件包括 Adobe Media Server/Ultrant Media Server/red5 等。
HTTP-FLVFLV (Flash Video) 是 Adobe 公司推出的另一种视频格式,是一种在网络上传输的流媒体数据存储容器格式。其格式相对简单轻量,不需要很大的媒体头部信息。整个 FLV 由 The FLV Header, The FLV Body 以及其它 Tag 组成。因此加载速度极快。采用 FLV 格式封装的文件后缀为 .flv。

5、VLC 播放器

关于什么是 vlc VLC 是一款自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及 DVD、音频 CD、VCD 及各类流媒体协议。 https://www.videolan.org/

当你想要好好探索播放器,或者对视频感兴趣,你可以下载这个软件,作用是播放一些不常见的视频文件格式

一些调研的思路

既然项目目前使用的是uni-app 当然了当初项目开发之初的选型也是我,为什么不用原生的支付宝小程序呢,大概因为我前几年写过 uni-app 大体了解生态中的功能。 我先去 uni-app 文档拔了一下,https://uniapp.dcloud.net.cn/component/live-player.html#live-player

AppH5微信小程序支付宝小程序百度小程序字节跳动小程序飞书小程序QQ 小程序快应用360 小程序京东小程序
app 端直接使用 videoh5 页面不支持支持X支持支持X支持XXX

初步的结论是 uni-app 环境下,没法搞 直播拉流操作

原生支付宝小程序 :不对外暴露 直播拉流的 能力,社区相关讨论如下

支付宝小程序 如何实时直播拉流 播放 rtmp 流媒体格式你好,支付宝小程序如何实现直播拉流(实时音视频播放),需要开通那些功能?

既然看了,uni-app 支付宝小程序 有关微信小程序的这块实现,可以自己读一下 微信小程序这块的说明

实现的推进

开始技术调研,是否支持内置的组件

  • 是 live-player
  • 否 能否接入第三方的播放器 (事实证明这种方式是不可行的)
  1. 调研 [支付宝小程序集成实时视频直播] 技术可行性 此功能点为内邀功能:不对外开放 可以尝试和支付宝方对接,确定能否对小万开放相关 API 该组件是原生组件,目前定向开放,需要申请权限并审核通过才能通过 开发简易 demo,验证 api 的准确性与可达性 文档中的 api 属性和方法仅能满足简易的开始直播 结束直播 全屏 等等操作
  2. 推进的结论 在支付宝小程序可以实现直播功能点,但是可扩展的小功能点不多 播放器需要针对特定业务进行二次封装
js
// 1、创建播放器上下文
this.livePlayerContext = my.createLivePlayerContext('live-player-id')

// 2、通过设备的deviceId获取rtmp直播流
// 3、心跳保持直播流的有效状态
js
 <live-player
    id="live-player-id"
    :src="livePlayerUrl"
    mode="live"
    :autoplay="false"
    :muted="false"
    object-fit="contain"
    style="width: 100%; height: 400rpx"
    orientation="vertical"
    @stateChange="onStateChange"
    @fullscreenChange="onFullscreenChange"
    @error="handleError"
  />

代码实现

html
<view class="page-body">
  <view>
    <live-player
      id="liveplayer"
      src="{{url}}"
      autoplay="{{true}}"
      mode="live"
      onStateChange="onStateChange"
      onError="onError"
      onFullscreenChange="onFullscreenChange"
    />
  </view>
  <view>
    <view class="info-area">视频源(src):</view>
    <input
      type="text"
      style="width:100%;"
      onInput="srcChanged"
      value="{{url}}"
    />
    <view class="section-body">播放状态展示:state/error/direction </view>
    <button type="default" class="info-area" plain="false">{{state}}</button>
    <button type="default" class="info-area" plain="false">{{error}}</button>
    <button type="default" class="info-area" plain="false">
      {{direction}}
    </button>
    <view class="section-body">接口展示 </view>
    <button type="default" class="btn-area-3" onTap="pause" plain>pause</button>
    <button type="default" class="btn-area-3" onTap="resume" plain>
      resume
    </button>
    <button type="default" class="btn-area-3" onTap="mute" plain>mute</button
    ><button type="default" class="btn-area-2" onTap="play" plain>play</button>
    <button type="default" class="btn-area-2" onTap="stop" plain>stop</button>
    <button type="default" class="btn-area-3" onTap="fullScreen0" plain>
      反向横屏
    </button>
    <button type="default" class="btn-area-3" onTap="fullScreen1" plain>
      竖屏全屏
    </button>
    <button type="default" class="btn-area-3" onTap="fullScreen2" plain>
      横屏全屏
    </button>
  </view>
</view>
js
Page({
    data: {
    url: "rtmp://ns8.indexforce.com/home/mystream",
    state: "0",
    direction: 90,
    error: "0",
    isMute: false,
    direction: 90,
},
onLoad() {
    this.liveplayerContext =
    my.createLivePlayerContext('liveplayer');
},
play() {
    this.liveplayerContext.play();
},
pause() {
    this.liveplayerContext.pause();
},
resume() {
    this.liveplayerContext.resume();
},
stop() {
    this.liveplayerContext.stop();
},
mute() {
    console.log("mute");
    this.data.isMute = !this.data.isMute;
    this.liveplayerContext.mute({
    ison: this.data.isMute,
    });
    console.log("mute finished, val=" + this.data.isMute);
},
fullScreen0() {
    this.liveplayerContext.requestFullScreen({
    direction: -90,
});
// setTimeout(() => { this.liveplayerContext.exitFullScreen() },
3000);
},
fullScreen1() {
this.liveplayerContext.requestFullScreen({
direction: 0,
});
// setTimeout(() => { this.liveplayerContext.exitFullScreen() },
3000);
},
fullScreen2() {
this.liveplayerContext.requestFullScreen({
direction: 90,
});
// setTimeout(() => { this.liveplayerContext.exitFullScreen() },
3000);
},
onError(e) {
console.log("onPushError, e=" + JSON.stringify(e));
this.setData({
error: e.detail.code,});
},
onStateChange(e) {
console.log("onStateChange, e=" + JSON.stringify(e));
this.setData({
state: e.detail.code,
});
},
onFullscreenChange(e) {
    console.log("arguments.length=" + arguments.length);
    console.log("onFullscreenChange, e=" + JSON.stringify(e));
    this.setData({
    direction: e.detail.direction + "-" +
    e.detail.fullScreen,
    });
    },
});

总结

定时器 延时器 视频播放,有可能有性能问题 (播放器所在页面的内存泄漏问题), 可以通过小程序页面推出后台、销毁等时机,保证定时器延时器清除

还有就是在企业级的项目中,是可以比个人开发者申请更多的内侧功能

属性名类型默认值描述
srcstring''直播源的 url 地址。可以支持 rtmp、http、https 等协议(和 video 组件类似)
modestring'live'默认 live,rtc 模式暂不支持
autoplayboolfalse是否自动播放。是否在组件一显示就 自动开始播放
mutedboolfalse是否静音
orientationstring"vertical"播放方向,可选 vertical、 horizontal
object-fitstring"contain"填充模式,可选 contain 和 fill
min-cachefloat1.0最小缓冲区
max-cachefloat3.0最大缓冲区
floating-modestringnonenone:无浮窗; page:页面内浮 窗; miniprogram:跨页面浮窗; (app:全局浮窗,暂时不对外开放)
onStateChangefunction播放状态变化
onFullScreenChangefunction全屏状态变化
onUserActionfunction用户操作事件,event.detail = {tag:"float_view"},tag 为用户操 作的元素,目前支持的 tag 有: float_view(浮窗)、float_view_close(浮窗关闭按钮)

微信公众号 前端诗人