• 纵享丝滑!Cesium + ffmpegserver 生成高质量动态视频【逐帧生成】


    工作中需要提供一些在三维场景下的视频动画素材,屏幕录制会出现掉帧等其他问题,看到 ffmpegserver 后,眼前一亮

    Cesium + ffmpegserver 生成高质量视频

    1.自建 ffmpegserver

    首先,克隆 ffmpegserver 仓库代码

    git clone https://github.com/greggman/ffmpegserver.js.git
    
    • 1

    安装依赖

    cd ffmpegserver.js && npm install
    
    • 1

    启动服务

    npm start
    
    • 1

    ffmpegserver 中有两个 demo 案例,可以打开源代码看看具体实现

    效果的预览地址是:

    1.普通 canvas案例: http://localhost:8080/test.html

    2.threejs 案例 http://localhost:8080/test2.html

    原理是通过一帧一帧截取图片,最后用 ffmpeg 逐帧将图片合成为视频。

    2. 在 cesium中 集成

    以定点环绕来举例

    首先,初始化 CCapture 实例

    const capturer = new CCapture({
      format: 'ffmpegserver',
      framerate: 60,
      onProgress: () => {},
      extension: '.mp4',
      name: 'cesium'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    开始环绕

    const lat = 45.2013
    const lng = 82.08887889
    const position = Cesium.Cartographic.fromDegrees(lng, lat);
    // 获取点位所在地形高度
    const updatedPosition = await Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [position]);
    const [destination] = updatedPosition;
    const height = destination.height;
    
    capturer.start();
    
    const center = Cesium.Cartesian3.fromDegrees(lng, lat, height);
    let heading = Cesium.Math.toRadians(40.0);
    const pitch = Cesium.Math.toRadians(-45.0);
    const range = 2000.0;
    let totalRotation = 0
    const speed = 1; // 环绕速度,每帧转多少度
    
    capturer.capture(viewer.canvas);
    
    function showVideoLink(url, size) {
      size = size ? ' [size: ' + (size / 1024 / 1024).toFixed(1) + 'meg]' : ' [unknown size]';
      let filename = url;
      const slashNdx = filename.lastIndexOf('/');
      if (slashNdx >= 0) {
        filename = filename.substr(slashNdx + 1);
      }
      // 视频下载链接
      console.log("http://127.0.0.1:8080" +  url)
    }
    
    function animate() {
      if (totalRotation >= 360) {
        if (screenRecording) {
          capturer.stop();
          capturer.save(showVideoLink);
        }
        totalRotation = 0;
        return;
      }
      viewer.render();
      capturer.capture(viewer.canvas); // 一定要加这一行,不然视频是纯黑的
      totalRotation += speed;
      heading = Cesium.Math.toRadians(x);
      viewer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));
      viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
      requestAnimationFrame(animate);
    }
    
    animate();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    Web前端:Flutter vs React Native——哪个最适合App开发?
    ELK Kibana的基本使用 (七)
    RISC-V 架构寄存器规范
    CMT2380F32模块开发17-ADC例程
    网络原理 --- 传输层Ⅱ TCP协议中的确认应答,超时重传和连接管理
    统计学习算法实现(01)——决策数
    uniapp封装mixins实现H5和微信小程序的微信支付
    Hbase 迁移小结:从实践中总结出的最佳迁移策略
    java学习一
    探究Vue 的脚手架-详细版
  • 原文地址:https://blog.csdn.net/twodogya/article/details/133650076