项目启动 | SooMooc 直播平台


前端所有代码已经同步到 GitHub Repo: EthanLuu/soomooc: React + TypeScript 实践,在线教学直播平台。 (github.com)

迫于课程实践要做一个在线教学直播平台,就拿 React 练练手吧。

既然是一个教学直播平台,就先起名叫做 SooMooc 了 🎉

技术栈说明

  • React:前端框架
  • React Ant Design:组件库
  • OBS:直播推流工具
  • livego:直播服务器
  • flv.js:网页视频播放器

初始化项目

因为之前有看过一个 React + TypeScript 的实战视频,这次干脆也试着用 TS 写咯。

先在命令行创建项目。

npm install -g create-react-app
npx create-react-app soomooc  --template typescript

修改一下 tsconfig.json 里的 compilerOptions,修改一下 baseUrl,便于以后的 import 操作。

"baseUrl": "./src",
code

antd

安装 antd 样式库。

在 TypeScript 中使用 - Ant Design

yarn add antd

修改 src/App.css,在文件顶部引入 antd 的样式。

@import '~antd/dist/antd.css';

craco

为了实现主题的自定义和模块化的 CSS 书写方式,我们需要安装 craco 插件,注意这里有两个包。

# 自定义主题
yarn add @craco/craco craco-less
# 模块化书写 CSS
yarn add @emotion/styled

安装完之后在根目录新建一个文件 craco.config.js,可以在这里自定义主题配色、字体等。

const CracoLessPlugin = require('craco-less')

module.exports = {
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            modifyVars: {
              // '@primary-color': 'rgb(0, 82, 204)',
              '@font-size-base': '16px',
            },
            javascriptEnabled: true,
          },
        },
      },
    },
  ],
}

这里把字体大小设置成 16px,是为了方便后续可以设置成 font-size: 62.5% ,最终实现1rem = 10px

修改一下 App.css

html {
  font-size: 62.5%;
}
html body #root .App {
  min-height: 100vh;
}

顺便改一下 package.json 里面的命令脚本。

code

commitlint

安装 commitlint,用于规范 git 提交格式。

conventional-changelog/commitlint: 📓 Lint commit messages (github.com)

  1. 安装库

    yarn add @commitlint/config-conventional @commitlint/cli -D
    
  2. 在项目根目录新建文件 commitlint.config.js

    module.exports = {extends: ['@commitlint/config-conventional']}
    
  3. 安装并配置 husky,用于在 git commit 前进行格式检查。

    # Install Husky v6
    yarn add husky --dev
    
    # Activate hooks
    yarn husky install
    
    # Add hook
    npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
    

提交格式如下:

git commit -m <type>[optional scope]: <description>

常用 type:

  • build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
  • ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
  • docs:文档更新
  • feat:新增功能
  • fix:bug 修复
  • perf:性能优化
  • refactor:重构代码(既没有新增功能,也没有修复 bug)
  • style:不影响程序逻辑的代码修改(修改空白字符,补全缺失的分号等)
  • test:新增测试用例或是更新现有测试
  • revert:回滚某个更早之前的提交
  • chore:不属于以上类型的其他类型(日常事务)

直播组件 demo

参考 gwuhaolin/reflv: react component wrap flv.js (github.com)

先写一个播放器的 demo,熟悉一下推拉流所需要的技术栈。

新建 src/components 文件夹,存放通用组件。

新建 src/screens 文件夹,存放页面相关组件。

image-20210508204130604

live-player.tsx

live-player.tsx 组件是对 flv.js 的封装。

import { useEffect, useRef } from 'react'
import flvjs from 'flv.js'

interface LivePlayerProps {
  type?: string
  url: string
}

export const LivePlayer = (props: LivePlayerProps) => {
  const flvRef = useRef<flvjs.Player>()
  const videoRef = useRef<HTMLVideoElement>(null)
  useEffect(() => {
    if (flvjs.isSupported()) {
      flvRef.current = flvjs.createPlayer({
        type: 'flv',
        isLive: true,
        cors: true,
        ...props,
      })
      if (videoRef.current) {
        flvRef.current.attachMediaElement(videoRef.current)
        flvRef.current.load()
      }
    }
  }, [props])

  return (
    <div className={'video-container'}>
      <video ref={videoRef} className={'video'} width="80%" controls>
        {`Your browser is too old which doesn't support HTML5 video.`}
      </video>
    </div>
  )
}

demo.tsx

demo.tsx 界面组件用于展示播放器。

/* @jsxImportSource @emotion/react */
import { LivePlayer } from 'components/live-player'
import styled from '@emotion/styled'

export const Demo = () => {
  return (
    <PlayerContainer>
      <h2 css={{ 'font-size': '3rem' }}>SooMooc Demo</h2>
      <LivePlayer url="http://localhost:7001/live/demo.flv" type="flv" />
    </PlayerContainer>
  )
}

const PlayerContainer = styled.div`
  text-align: center;
`

App.tsx

将 demo 界面组件包到 App 里。

import './App.css'
import { Demo } from 'screens/demo'

function App() {
  return (
    <div className="App">
      <Demo/>
    </div>
  )
}

export default App

直播流程

在本地试用一下这个播放界面。

在开始推流之前,要先知道推流的地址,本项目使用 livego 作为推拉流的中介服务器。

在 GitHub 的 livego 上直接下载最新版 release 安装即可,我这边是 windows 版。

当然你也可以按照说明里下载源码自己进行编译

安装完成后直接在本地打开 livego.exe 运行服务器即可。

image-20210508212204659

可以看到这边的 RTMP 的接口是 1935,由于我们的服务器架在本地,所以推流的服务器地址应该是 rtmp://localhost:1935

主播需要安装并打开 OBS,对需要分享的屏幕进行自定义,点击左下角 ➕ 可以添加文字、图片、摄像头等。

image-20210508210837652

点击右下角设置,在推流界面填写我们刚刚知道的服务器地址和密钥。

image-20210508213903915

在 OBS 界面点击开始推流,此时 OBS 右下角会显示推流的速度和时间等信息。

image-20210508214024788

回到项目根目录,确认一下 demo.tsx 中的拉流地址是否一致。

<LivePlayer url="http://localhost:7001/live/demo.flv" type="flv" />

运行 React 项目。

yarn start

打开浏览器即可看到

image-20210508221140389

本地推拉流延迟大约2-3s,第一步大功告成。image-20210509193426944