伯索开放平台
首页API文档SDK文档伯索官网
首页API文档SDK文档伯索官网
  1. SDK文档
  • 直播SDK接入
    • WEB版本
      • WEB版本
    • iOS版本
      • IOS版本
    • Android版本
      • Android版本
  • 微课SDK接入
    • WEB版本
      • WEB版本
    • iOS版本
      • IOS版本
    • Android版本
      • Android版本
  • 批注SDK接入
    • Web版本
      • Web版本
    • iOS版本
      • IOS版本
    • Android版本
      • Android版本
  • 签名加密
    • 签名加密
  • 回调接口接入流程
    • 回调接口接入流程
  • 文档解析接入方式
    • 文档解析接入方式
  • 历史课堂接入方式
    • 历史课堂接入方式
  • 历史课堂转视频接入方式
    • 历史课堂转视频接入方式
  • 历史课堂/微课下载接口
    • 历史课堂/微课下载接口
  1. SDK文档

历史课堂转视频接入方式

伯索历史课堂格式是私有格式, 不是标准的MP4格式, 针对客户需要转为普通的MP4格式视频做数据留存,我们建议使用如下技术方案来实现。
一、基于服务端录制实现
在项目中,需要加入录制会议的功能。在服务器端,通过进入需要录制的房间,然后将房间的声音、视频的情况录制下来,保存到视频文件中。
二、技术选型(puppeteer + puppeteer-stream)
puppeteer介绍
Puppeteer是一个Node库,它提供了各种高级的API,通过DevTools协议来控制浏览器(chrome, chromium)。可以理解成为一个headless chrome浏览器。当前,我们也可以通过option,设置为有UI的浏览器。
转历史课堂录制方案1.png
Puppeteer api
Puppeteer api
**API **** 描述 **
Browser浏览器实例,可以包含多个BrowserContext
BrowserContext对应浏览器的一个上下文回话。例如普通的浏览器中打开隐身模式的浏览器,具有独立的cookie和cache, 拥有多个page
Page表示一个Tab页面: browser.newPage()
Frame每个页面有一个主框架(page.MainFrame(),可以拥有多个子框架,由iframe标签创建
ExecutionContextJavaScript执行环境。每一个frame有一个默认的JavaScript执行环境
ElementHandle对应Dom的一个元素节点,通过该实例可以实现对元素的点击,操作
JsHandle对应Dom中的JavaScript对象,ElementHandle继承于JSHandle.由于我们无法直接操作 DOM 中对象,所以封装成 JsHandle 来实现相关功能
CDPSession可以直接与原生的 CDP 进行通信,通过 session.send 函数直接发消息,通过 session.on 接收消息,可以实现 Puppeteer API 中没有涉及的功能
Coverage获取JavaScript和css代码覆盖率
Tracing抓取性能数据进行分析
Response页面收到的响应
Request页面发出的请求
puppeteer-stream 是什么?
会议录制其实就是讲页面的音频视频转换为流,然后将流存入文件中。puppeteer-stream通过调用Chrome Extension API: chrome.tabCapture.capture, 返回整个页面的音频视频流。 当然,我们也可以不使用puppeteer-stream,自己使用Chrome Extension API来捕获页面的stream流,包含了音频和视频。然后通过MediaRecorder创建一个变量,并监听新进来的stream, 最后将该流保存为 webm格式的视频文件。
tips: chrome.tabCapture.capture: 捕获当前活动标签页的可视区域。该方法只能在扩展程序被调用之后在当前活动网页上使用,与 activeTab 的工作方式类似。
三、实现录制
puppeteer-stream 已经puppeteer引入改造,在实际的录制中,我们只需要引入puppeteer-stream即可。按照以下步骤实现功能:
打开浏览器
访问需要录制的页面
获取录制页面的stream对象,存放如webm格式视频文件
打开浏览器
这里需要注意defaultViewport 和 --window-size需要结合配置,让窗体才能100%打开。不然打开后是一个很小的窗体。
args参数可以访问这
import { launch } from "puppeteer-stream";
let width = 1920,
  height = 1080;
this.browser = await launch({
  headless: true, 
  args: [
    "--no-sandbox",
    "--disable-setuid-sandbox",
    `--window-size=${width},${height}`,
    "--autoplay-policy=no-user-gesture-required",
    // '--remote-debugging-port=3333',
    // "--auto-open-devtools-for-tabs",
  ],
  defaultViewport: {
    width: 0,
    height: 0,
  },
  ignoreDefaultArgs: ["--disable-extensions", "--mute-audio"],
});
访问需要录制的页面
创建一个page, 在page中输入需要访问的地址, 并处理界面上各种点击事件操作。
如果需要在页面里执行一些操作,可以通过 page.evaluate(function, option)方法实现。这相当于在控制台编写代码。function 为控制台执行的内容,option是想从外面传递到内部的参数。
 const result = await page.evaluate(
  async (option: { [key in string]: any }) => {
    let { _client } = window as any;
    console.log(options.id);
    return JSON.stringify(joinResult)
  },
  {
    id: this.id,
  }
);
保存视频文件
getStream会返回整个页面的stream,将该流生成一个webm格式的视频。
import fs from "fs";
import { Page } from "puppeteer";
import { getStream } from "puppeteer-stream";
 this.stream = await getStream(this.page as Page, {
    audio: true,
    video: true,
    frameSize: 20,
  });

  this.file = fs.createWriteStream(`${this.filePath}.webm`);
  this.stream.pipe(this.file);
四. xvfb-run 虚拟桌面
因为最终部署需要在服务器上走docker, 都是无桌面的方式。但是chrome 是不支持 headless(无头)模式下注入插件。这里我们可以使用xvfb还实现,该软件会帮我们生成一个虚拟桌面,然后代码就会在改虚拟的左面进行运行。
xvfb-run --server-args="-screen 0, 3840x2160x24" npm run server
五. 参考Demo
点击下载
修改于 2023-11-16 06:32:50
上一页
历史课堂接入方式
下一页
历史课堂转视频接入方式
Built with