电脑装配网

西瓜视频播放器+ SRS 实现直播方案

 人阅读 | 作者yiyi | 时间:2023-06-13 06:18

直播作为近几年比较火的方向,吸引了像我这样的小白不断在音视频的边缘不断试探。“宇宙的尽头是直播”,不论是娱乐直播还是直播带货,都已经成为现在人们生活中不可获取的一部分。 今天我们就来实现一个直播的 demo,我们来看一下整个直播的过程:

SRS 流媒体服务器

为了方便我推荐使用云 SRS,可以基于宝塔一键部署,如果没有云服务器可以根据官方 github 自行编译(难度较大,不推荐新手选择此方式)。 在宝塔的软件商店中搜索 SRS(免费的,如果显示购买直接点击购买即可),点击安装

插件包安装完成之后打开,安装云 SRS,这个过程比较耗时,耐心等待……

安装完成之后需要等待几分钟,云 SRS 内部的依赖启动需要一定的时间,等启动完成之后打开管理面板,设置管理员密码之后,进入系统设置菜单,找到 OpenAPI 选项,我们的后端服务需要根据这两个接口来获取串流秘钥。

后端服务

这边的业务服务器我们使用 Node 来实现,在这个过程中负责客户端鉴权以及获取串流秘钥,这里我选用 Midway(全凭个人喜好,可以选择任何其他的框架 Express、Koa、nest 等)。 我们这里提供两个接口:

主播获取推流地址和串流秘钥;获取房间信息(最主要是 streamKey)

C++音视频学习资料免费获取方法:关注音视频开发T哥,点击正在跳转即可免费获取2023年最新C++音视频开发进阶独家免费学习大礼包!

获取串流秘钥

使用 ApiSecret 从云 SRS 的 OpenAPI来获取秘钥,过程如下

以下是代码实现(忽略实体、配置等部分,只展示流程)

@Controller('/anchor') export class AnchorController { @Inject() ctx: Context; @Inject() roomService: RoomService; @Inject() anchorService: AnchorService; @Inject('short-uuid') short; @Config('srs') srs; // 配置了服务器 IP 和 ApiSecret // 判断主播身份 validateAnchor(user: UserModel) { if (!user || user.role !== UserRole.ANCHOR) // 如果没有用户(可能被冻结或者注销)或者没有权限抛出异常 throw new CustomError( INSUFFICIENT_PERMISSIONS.CODE_1, INSUFFICIENT_PERMISSIONS.MSG_1 ); } // 生成向直播间串流秘钥(限制主播身份) @Post('/streamKey') async createStreamKey() { const userId = this.ctx.state.user.uid; const user = await this.anchorService.getAnchorWithRoom(userId); // 身份判断 this.validateAnchor(user); // 将主播关联的直播间进行串流秘钥重置 const key = this.short.generate(); const room = user.liveRoom; room.streamKey = key; // 保存新的串流秘钥 await this.roomService.saveRoom(room); // 获取 token (makeHttpRequest 相当于 fetch, 做请求用) const token = await makeHttpRequest( 'http://' + this.srs.url + '/terraform/v1/mgmt/secret/token', { method: 'POST', dataType: 'json', contentType: 'json', data: { apiSecret: this.srs.apiSecret, }, } ); // 使用 token 获取 secret const srsSecret = await makeHttpRequest( 'http://' + this.srs.url + '/terraform/v1/hooks/srs/secret/query', { method: 'POST', dataType: 'json', contentType: 'json', data: { token: token.data.data.token, }, } ); return { url: 'rtmp://' + this.srs.url + '/live/', key, secret: srsSecret.data.data.publish, }; }}

主播每次获取串流密钥会进行重置,防止泄露。

获取直播间信息

获取直播间信息相对简单,只需要查询数据返回即可

@Controller('/live') export class LiveController { @Inject() ctx: Context; @Inject() roomService: RoomService; // 获取直播间相关数据 @Get('/room/:roomId') async getRoomById(@Param('roomId') room: string) { const res: any = await this.roomService.getRoomById(room); if (!res) { throw new CustomError(ROOM_NOT_FOUND.CODE, ROOM_NOT_FOUND.MSG); } // 粉丝数量取值 res.fans = res.fans.length; return res; }}

xgplayer(西瓜播放器)

播放器我当初对比过 MuiPlayer 和 xgPlayer,最终选择了西瓜(背靠大厂、集成度更高)。 我们使用 http-flv 的形式来进行推拉流,所以我们需要同时安装 xgplayer 和 xgplayer-flv

$ pnpm add xgplayer xgplayer-flv

前端框架层面我使用了 Vue3,代码如下(只是播放器相关部分,不是最终成品的代码)

<template> <div class="room-video" id="mse"></div></template><script setup lang="ts">import "xgplayer";import FlvPlayer from "xgplayer-flv";// 播放器const playerRef = ref<FlvPlayer>();onMounted(async () => { room.info = await getRoomInfo(props.roomId); if (room.info.isLiving) { initPlayer(); }}); // 初始化播放器function initPlayer() { if (playerRef.value) { playerRef.value.destroy(); } playerRef.value = new FlvPlayer({ id: "mse", // 容器元素 ID url: import.meta.env.VITE_VIDEO_URL + room.info.streamKey + ".flv", // 拉流地址 isLive: true, // 直播模式 autoplay: true, // 自动播放 height: 500, // 高 width: 888, // 宽 pip: true, // 画中画 lang: "zh-cn", ignores: ["replay"], // 忽略内置控件 danmu: { // danmu 配置 comments: [], }, });}// socket 收到消息之后通过 player 实例调用 instace.danmu.sendComment 即可动态添加弹幕</script>

成品展示

主播面板获取推流码,复制到 OBS 中开始推流

观众进入直播间获取直播流进行播放

作者:枫景 链接:https://juejin.cn/post/7152397283248570404

#音视频开发##程序员##把地球的故事讲给宇宙#


文章标签:

本文链接:『转载请注明出处』