项目启动 | 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",
antd
安装 antd
样式库。
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
里面的命令脚本。
commitlint
安装 commitlint
,用于规范 git 提交格式。
conventional-changelog/commitlint: 📓 Lint commit messages (github.com)
-
安装库
yarn add @commitlint/config-conventional @commitlint/cli -D
-
在项目根目录新建文件
commitlint.config.js
module.exports = {extends: ['@commitlint/config-conventional']}
-
安装并配置
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
文件夹,存放页面相关组件。
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
运行服务器即可。
可以看到这边的 RTMP 的接口是 1935,由于我们的服务器架在本地,所以推流的服务器地址应该是 rtmp://localhost:1935
主播需要安装并打开 OBS,对需要分享的屏幕进行自定义,点击左下角 ➕ 可以添加文字、图片、摄像头等。
点击右下角设置,在推流界面填写我们刚刚知道的服务器地址和密钥。
在 OBS 界面点击开始推流,此时 OBS 右下角会显示推流的速度和时间等信息。
回到项目根目录,确认一下 demo.tsx
中的拉流地址是否一致。
<LivePlayer url="http://localhost:7001/live/demo.flv" type="flv" />
运行 React 项目。
yarn start
打开浏览器即可看到
本地推拉流延迟大约2-3s,第一步大功告成。