码上掘金不仅可以写 PPT,还可以录视频

sxkk20081年前知识分享102

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

短视频作为新时代的产物,到现在才发展了几年的时间,创作者们看到了短视频的红利,有不少人已经通过视频录制和知识付费的方式实现了流量的变现,当然这只是一少部分人,还有成千上万的热涌向这个风口,他们在干什么?他们正在学习视频录制、视频剪辑的路上。

短视频的入门门槛虽然很低,但想要获得流量还是有一定门槛的,我今年的 flag 之一就是学习视频制作剪辑,前段时间剪了一个视频总共 1 分 20 秒,就花了我一整天的时间,那么我在想,作为前端工程师能不能开发一款产品,让短视频创作更低,后来我看到了一款贴合程序员的产品 Slidev,可以让我们使用 markdown 写 PPT,并且可以录制视频。

前端实现视频录制

好了,正文开始,本文基于我之前写的一篇文章《Markdown 写 PPT 是如何实现的?》,我们要在此之上实现视频录制的功能。

使用 WebRTC 的 API 可以实现了一个录音、录像、录屏工具

我们先使用 React 写一个录制的组件

import React, { useState, useRef } from 'react'
import ReactDom from 'react-dom'

const App = () => {
  const [videoUrl, setVideoUrl] = useState<string>('')

  // 结束
  const stopRecord = async () => {}

  // 开始
  const startRecord = async () => {}

  const pauseRecord = async () => {}

  const resumeRecord = async () => {}

  return (
    <div>
      <h1>React 录屏h1>
      <video className="video" src={videoUrl} controls />
      <h2>
        <button onClick={startRecord}>开始button>
        <button onClick={pauseRecord}>暂停button>
        <button onClick={resumeRecord}>恢复button>
        <button onClick={stopRecord}>停止button>
      h2>
    div>
  )
}

ReactDom.render(<App />, document.getElementById('app'))

上面有一个 video 标签,以及 开始、停止、暂停、恢复、几个按钮用于控制屏幕的录制。

const mediaStream = useRef<MediaStream>()
const audioStream = useRef<MediaStream>()
const recorder = useRef<MediaRecorder>()
const mediaBlobs = useRef<Blob[]>([])

我们使用 useRef 来存放数据,mediaStream 存放视频流, audioStream 存放音频流,recorder 存放视频录制对象,mediaBlobs 将流转化为 Blob 对象。

下面代码是开始录制和结束录制的逻辑:

// 结束
const stopRecord = async () => {
  recorder.current?.stop()
  // 不仅让 MediaRecorder 停止,还要让所有轨道停止
  mediaStream.current?.getTracks().forEach((track) => track.stop())
}

// 开始
const startRecord = async () => {
  // 录屏接口
  mediaStream.current = await navigator.mediaDevices.getDisplayMedia({ video: true })
  // 主动停止录制
  mediaStream.current?.getTracks()[0].addEventListener('ended', () => {
    stopRecord()
  })
  // 录音接口
  audioStream.current = await navigator.mediaDevices.getUserMedia({ audio: true })
  // 往视频流中加入音频流
  audioStream.current
    ?.getAudioTracks()
    .forEach((audioTrack) => mediaStream.current?.addTrack(audioTrack))
  // 录制视频流
  recorder.current = new MediaRecorder(mediaStream.current)

  // 将 stream 转成 blob 来存放
  recorder.current.ondataavailable = (blobEvent) => {
    mediaBlobs.current.push(blobEvent.data)
  }
  // 停止时生成预览的 blob url
  recorder.current.onstop = () => {
    const blob = new Blob(mediaBlobs.current, { type: 'video/mp4' })
    //来生成预览链接
    const mediaUrl = URL.createObjectURL(blob)
    setVideoUrl(mediaUrl)
  }

  recorder.current?.start()
}

上述代码先通过 navigator.mediaDevices.getDisplayMedia 获取用户选中的录屏流,接着通过 navigator.mediaDevices.getUserMedia({ audio: true })获取音频流,然后通过 mediaStream.current?.addTrack(audioTrack) 将所有音频流加入到视频流中。再通过 MediaRecorder 录制视频流,通过 ondataavailable 来存放当前流中的 Blob 数据。 最后一步,调用 URL.createObjectURL 来生成预览链接。

下面是暂停和恢复的实现代码,是 MediaRecorder 提供的方法

const pauseRecord = async () => {
  recorder.current?.pause()
}

const resumeRecord = async () => {
  recorder.current?.resume()
}

这样就实现了一个在线录屏的 Demo,一起在“码上掘金”中看看效果吧。

代码片段

实现幻灯片演讲录制

接下来我们将视频录制的功能集成到之前的幻灯片中,只需要将上面的 App 组件改成 RecordView 组件,并且通过 position: fixed; 属性将操作按钮定位到幻灯片之上。

录制完成后,通过创建一个 a 标签,就可以实现自动下载。

下面是自动下载的代码:

export function downloadBlob(blob, filename) {
  let element = document.createElement('a')
  element.setAttribute('href', blob)
  element.setAttribute('download', filename)
  element.style.display = 'none'
  document.body.appendChild(element)
  element.click()
  document.body.removeChild(element)
}

同样我们在“码上掘金”中看看效果吧。 代码片段 鼠标移动到左下角会显示操作按钮,我们还可以点击编辑按钮对幻灯片进行实时编辑,这么简单就实现了想要的效果,简直不可思议。

竖屏录制

目前短视频都是竖屏的,我们那么能否录制竖屏版的视频呢?答案是可以的,但是在“码上掘金”中不能,因为“码上掘金”是一个代码编辑器,在移动端无法访问,因此我还将这个应用部署到了 vercel 上,大家可以通过这个地址访问 :

http://ppt.runjs.cool/

打开 Chrome devtools 选择手机调试模式,选中一个合适的型号,便可以开始录制了,录制的时候选中当前网页就可以了。

竖屏录制

这样保存下来的视频便是竖屏的。

最后,我将这个工程的源码上传到了 GitHub:https://github.com/maqi1520/vitejs-md-ppt

目前还比较粗糙,经过精雕细琢后可能会成为一个好产品,先占个坑吧!

小结

本文用 WebRTC 的 API 简单地实现了一个录屏工具,并且可以结合 markdown 写 PPT 实现录制幻灯片的功能,我们一起来梳理下录屏的实现逻辑

  • 使用 getUserMedia 可获取麦克风以及摄像头的流;
  • 使用 getDisplayMedia 可获取屏幕的视频、音频流;
  • 使用 MediaRecorder 可监听 stream, 从而获取 Blob 数据;
  • 最后使用 URL.createObjectURLBlob 转为下载链接;

以上就是本文全部内容,如果对你有帮助,可以随手点个赞,这对我真的很重要,希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。

相关文章

使用 phaser3 从零实现一个战疫小游戏

前言在本文中,我将从零开发一个 H5 游戏,主要使用 phaser3 来制作的游戏。结合当下疫情的严峻形式,我也将一些元素融入到这款游戏中,同时希望疫情早日结束,早点摘下口罩,可以看到彼此脸上洋溢的笑...

基于AI技术的家居智能化解决方案——改善生活质量的新时代

基于AI技术的家居智能化解决方案——改善生活质量的新时代

  智能家居已经成为现代社会家庭生活的热门话题。随着人工智能技术的不断发展和应用,越来越多的家居设备开始拥有自主学习和智能化操作的能力。AI家居应用正成为改善生活质量和提供便...

人工智能在科技领域的应用与发展趋势

人工智能在科技领域的应用与发展趋势

  随着科技的不断进步和发展,人工智能已经成为当下炙手可热的话题。作为中科技的中心,人工智能在各个领域中扮演着重要的角色。本文将探讨人工智能在科技领域的应用和未来的发展趋势。...

AI绘画:让艺术创作更加普惠化

AI绘画:让艺术创作更加普惠化

  随着人工智能技术的不断发展,它在各个领域的应用不断拓展。在艺术领域,AI也开始逐渐应用起来,其中一个突出的应用便是AI教绘画。AI绘画通过人工智能算法模拟人类绘画的过程,...

AI人工智能在当今社会中的应用及未来发展前景

AI人工智能在当今社会中的应用及未来发展前景

  近年来,随着科技的飞速发展,AI人工智能成为了全球瞩目的焦点。AI人工智能不仅仅是一项新兴技术,更是对社会转型和经济发展产生深远影响的重要因素。本文将探讨AI人工智能在各...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。