用声网 Cloud Player 在直播推流应用中推流视频

我在之前的一篇文章中探讨了怎么用声网媒体推送服务(视频直播系统)把直播推流发布到第三方平台(如 Youtube、Facebook 和 Twitch 等)。本文在那篇文章的基础上,教大家怎么用声网 Cloud Player 把云视频推流给视频通话/直播推流中的所有用户。


前期准备

  • Node.js LTS
  • 能熟练使用 React 和 Node/Express


设置

大家可以在 cloudplayer branch 获取已完成的项目。本项目基于之前搭建的项目而搭建,如果想跟着我的步骤进行编码,可以从 GitHub 上复制所有内容。

git clone https://github.com/EkaanshArora/Agora-Web-UIKit-RTMP.git
cd Agora-Web-UIKit-RTMP

安装依赖:npm i


1.开启 RTMP 转换器

首先,打开声网控制台,找到 Usage 选项卡,从下拉菜单中选择你的项目,然后,选中子菜单 RTMP Converter,点击 Enable RTMP Converter,开启转换器。

1


2.获取用户凭证

打开 RESTful API page,点击 Add Secret 按钮,把用户 ID 和用户机密复制到一个文本文件中,我们用这些凭证从后端服务调用声网Agora Cloud Player 终端。另外,可以从控制台的项目管理选项卡里获得 App ID。

后端会监听 React 前端的请求。我们先添加一个按钮,向网站发送这个请求。


3.开启声网Agora Cloud Player 服务

用 App ID 登录声网支持,发送请求,开启声网Agora Cloud Player 服务。


已完成的步骤

执行 npm start ,在主机上打开网页服务器,先从 ./src/App.tsx 和文件开始,替换 <RTMP> 组件,添加新组件 CloudPlayer

...
import CloudPlayer from './CloudPlayer'
...
const VideocallUI = () => {
...
      <div style={styles.containerInner}>
        <RTMP />
        <CloudPlayer />
      </div>
...

然后,创建一个新文件来定义 CloudPlayer 组件。

import { useState } from 'react';

const serverUrl = "" // enter the backend url 
// you can find a demo project here: (https://github.com/EkaanshArora/Agora-Cloud-Player-Backend)

const requestBody = {
  channel: "test",
  uid: 1,
  token: null,
  url: "" // enter video url
}

const CloudPlayer = () => {
  const [isBtnDisabled, setBtnDisabled] = useState(false)
  
  const playVideo = async () => {
    setBtnDisabled(true)
    let res = await fetch(serverUrl, {
      headers: {
        'Content-Type': 'application/json',
      },
      method: 'POST',
      body: JSON.stringify(requestBody)
    })
    let json = await res.json()
    console.log(json)
    setBtnDisabled(false)
  }

  return (<>
      <div style={isBtnDisabled ? disabledBtn : btn} onClick={() => {
        if (!isBtnDisabled) {
          playVideo()
        }
      }}>
        {isBtnDisabled ? 'Requesting...' : 'Stream Video from the Cloud'}
      </div>
    </>
  )
}

const btn = { backgroundColor: '#007bff', cursor: 'pointer', borderRadius: 5, padding: 5, color: '#ffffff', fontSize: 20, margin: 'auto',  paddingLeft: 10, paddingRight: 10}
const disabledBtn = { backgroundColor: '#007bff55', borderRadius: 5, padding: 5, color: '#ffffff', fontSize: 20, margin: 'auto', paddingLeft: 20, paddingRight: 20}

export default CloudPlayer;

CloudPlayer 是一个简单的组件,用来渲染推流云视频的按钮。然后,搭建 serverUrl 并对其进行定义。另外,定义 playVideo 函数,这个函数用 requestBody 向后端端点发送请求,我们可以在 requestBody 中定义频道名、声网 Cloud Player 服务的 UID、RTC 令牌和要播放的视频的 URL。

注意:视频 URL 必须是可公开访问的。


搭建后端服务

我们会使用 Express 搭建一个后端服务,这个后端服务会监听网站前端的请求,根据需要的凭证调用声网 Cloud Player 的端点。大家可以在 GitHub 中找到搭建后端服务的代码,其中的 readme 文件里有将其快速部署到 Heroku 上的按钮。

然后,我们输入库。我们用 Fetch 来发出 HTTP 请求,用 Express 管理服务器,用 dotenv 使用 .env 文件存储凭证,用 bodyParser 从传入的请求中解析 JSON 有效载荷。另外,cors 是一个实现跨源资源共享(CORS)的中间件。

import fetch from 'node-fetch'
import express from 'express'
import dotenv from 'dotenv'
import bodyParser from 'body-parser'
import cors from 'cors'


const app = express();
// setup cors
app.use(cors({origin: '*', methods: ['GET', 'POST', 'DELETE']}))
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json());
dotenv.config();

const PORT = process.env.PORT || 8080;
const APP_ID = process.env.APP_ID;
const REST_KEY = process.env.REST_KEY;
const REST_SECRET = process.env.REST_SECRET;
const region = 'na'
const auth = 'Basic ' + Buffer.from(REST_KEY + ':' + REST_SECRET).toString('base64');
...

然后,我们定义 Express app 对象,使用相应的中间件,初始化 dotenv,定义常量。我们需要 .env 文件设置中的用户凭证,将凭证编码,生成一个基本的认证标头,然后重命名 .env.example 文件,添加具体细节。

APP_ID=30a6bc899.............
REST_KEY=58cb3034............
REST_SECRET=93803f1..........
PORT=8080
...
const play = async (req, resp) => {
  resp.header('Acess-Control-Allow-Origin', '*');

  const channelName = req.body.channel;
  if (!channelName) {
    return resp.status(500).json({ 'error': 'channel is required' });
  }

  const uid = req.body.uid;
  if (!uid) {
    return resp.status(500).json({ 'error': 'uid is required' });
  }

  const url = req.body.url;
  if (!url) {
    return resp.status(500).json({ 'error': 'url is required' });
  }
  
  const token = req.body.token;
  ...

接下来,定义 play 函数,这个函数接收请求和响应。我们给响应对象添加 access-control-allow-origin 标头,从请求中获取 channelNameuidurltoken ,如果请求中没有这些内容,我们会发送 500 错误提示。

...
const headers = {
    'Authorization': auth,
    'Content-Type': 'application/json',
  }

  const data = {
    player:
    {
      streamUrl: url,
      channelName: channelName,
      token: token,
      uid: uid,
      idleTimeout: 300,
      name: "test"
    }
  }

  const res = await fetch(
    `https://api.agora.io/${region}/v1/projects/${APP_ID}/cloud-player/players`,
    {
      method: 'POST',
      body: JSON.stringify(data),
      headers: headers
    });
  const json = await res.json()

  console.log(json)
  return resp.json(json);
}
...

然后,我们为向声网 Cloud Player 端点发出的请求定义 headersdata ,详见这里。 我们用 fetch 等待响应,将其登录到控制台,再返回前端。

...

const ping = (req, resp) => {
  resp.send({message: 'pong'});
}

app.post('/play' , play);
app.get('/ping', ping)

app.listen(PORT, () => {
  console.log(`Listening on port: ${PORT}`);
});

我们会定义一个 ping 函数来确保正确配置后端服务器。然后,定义服务路由,用 play 函数来调用 /play POST 路由,用 ping 函数调用 /ping GET 路由,使用 listen 方法来监听定义端口的请求。

以上就是我们需要的所有代码。可以执行 node index.js 在本地运行服务,或使用 此链接 将其托管在 Heroku 上。


总结

如果大家发现了可以添加在后端服务(视频直播系统)上的好用功能,欢迎随时复刻资源库并添加拉取请求。谢谢大家~

欢迎随时在 UIKit 项目库后端库 提出功能需求或报告 bug~


原文作者:Ekaansh Arora
原文链接:Streaming Videos in Your Livestream Using the Agora Cloud Player
推荐阅读
相关专栏
SDK 教程
167 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。