电话咨询
QQ咨询
微信咨询
返回顶部

微信小程序录像功能实现:5步完成视频录制、预览与上传

微信小程序的录像功能,表面上看是调用一个API,但实际开发中,你会发现“能录像”和“录得好、录得稳、能上传”完全是两码事。我见过不少新手,照着文档写完代码,结果在iPhone上黑屏,或者在Android上录制出来的视频只有几KB。这篇文章,咱们就从头到尾把录像功能拆开揉碎了讲,重点落在那些文档里没写、但实际开发必踩的坑上。

一、录像前的准备:权限与组件选择

一上来就写 wx.startRecord,但这是旧接口,早已废弃。现在统一使用 wx.createMediaContainerCameraContext。这里有个关键区别:MediaContainer 适合做视频合成(比如录像后加滤镜),而单纯录像用 CameraContext.startRecord 更轻量。

权限申请是个容易忽略的细节。小程序在iOS上需要同时勾选“相机”和“麦克风”权限,但Android上部分机型(比如小米)还需要在manifest里单独声明录音权限。如果你只勾选了相机,用户在Android上录像时,画面正常但没声音,这就是权限遗漏导致的。

举个例子,我在一个医疗问诊小程序里,用户反馈录像没声音。排查后发现,requiredPrivateInfos 里只写了 "camera",加上 "microphone" 后问题解决。代码配置如下:

// app.json
{
  "requiredPrivateInfos": ["camera", "microphone"]
}
二、核心实现:从Camera组件到录像控制

Camera组件是录像的基础。但要注意,它有一个 mode 属性,默认是 "normal",如果你想录像时画面更流畅,可以改成 "scanCode""custom"。实测在低端Android机上,mode="normal" 会导致录像时画面卡顿,改成 "custom" 后帧率明显提升。

下面是录像的核心代码逻辑,注意我用了 try-catch 包裹,因为录像过程中用户可能突然切到后台,导致API调用失败:

// page.wxml


// page.js
Page({
  data: {
    isRecording: false,
    tempVideoPath: ''
  },
  startRecord() {
    const ctx = wx.createCameraContext('myCamera');
    ctx.startRecord({
      timeoutCallback: () => {
        // 超过最大录制时间(默认30秒)自动停止
        this.stopRecord();
      },
      success: () => {
        this.setData({ isRecording: true });
      },
      fail: (err) => {
        console.error('录像启动失败', err);
        wx.showToast({ title: '录像启动失败', icon: 'none' });
      }
    });
  },
  stopRecord() {
    const ctx = wx.createCameraContext('myCamera');
    ctx.stopRecord({
      compressed: true, // 压缩视频,减少体积
      success: (res) => {
        this.setData({
          isRecording: false,
          tempVideoPath: res.tempVideoPath
        });
        // 这里可以预览或上传
        this.previewVideo(res.tempVideoPath);
      },
      fail: (err) => {
        console.error('停止录像失败', err);
      }
    });
  }
});

注意 compressed: true 这个参数。如果不加,录出来的视频体积会非常大,1分钟可能达到100MB以上。但压缩也会带来画质损失,如果你的场景需要高清录像(比如教学录屏),可以设为 false,然后在上传时用后端进行压缩。

三、录像中的实时反馈:倒计时与状态提示

用户录像时,如果没有任何反馈,会感到迷茫。我习惯在录像时显示一个倒计时,同时用震动提示开始和结束。这里有个技巧:wx.vibrateShort 在iOS上只能调用一次,连续调用会失败,所以最好用 setInterval 控制频率。

倒计时的实现:

// 假设最大录制30秒
let remaining = 30;
this.timer = setInterval(() => {
  remaining--;
  if (remaining <= 0) {
    clearInterval(this.timer);
    this.stopRecord();
  }
  this.setData({ countdown: remaining });
}, 1000);

// 开始录像时震动
wx.vibrateShort({ type: 'medium' });

这里有个坑:当用户手动停止录像时,一定要清除定时器,否则界面会显示负数。我在一个社交小程序里就遇到过,用户录像10秒后手动停止,结果倒计时还在跑,显示“-20秒”,非常尴尬。

四、录像后的处理:预览与上传

录完视频后,用户通常希望预览一下。用 wx.previewMedia 可以同时预览图片和视频,但注意它只支持临时路径,不支持网络路径。如果你需要用户确认后再上传,可以先用 VideoContext 播放:

previewVideo(path) {
  const videoContext = wx.createVideoContext('myVideo');
  this.setData({ videoPath: path }, () => {
    videoContext.play();
  });
}

上传视频时,用 wx.uploadFile。但视频文件通常较大,上传时间较长,最好显示一个进度条。可惜 wx.uploadFile 本身不支持进度监听,需要自己用 wx.request 配合 XMLHttpRequest 实现,或者用第三方SDK。这里有个折中方案:先压缩视频再上传,可以显著减少等待时间。

压缩视频可以用 wx.compressVideo,但注意它只支持临时路径,且压缩后的视频可能丢失音频。我在一个教育类小程序里,压缩后音频不同步,后来发现是码率设置太低,调整 bitrate 到 1Mbps 后解决:

wx.compressVideo({
  src: tempVideoPath,
  quality: 'medium',
  bitrate: 1024, // 码率,单位kbps
  success: (res) => {
    // 上传压缩后的视频
    this.uploadVideo(res.tempFilePath);
  }
});
五、兼容性处理:各机型踩坑实录

录像功能在真机上问题最多。我整理了几个高频问题:

1. iPhone XS 及以上机型录像黑屏
原因是这些机型默认使用HEVC编码,而小程序的Camera组件在部分版本下不支持。解决方案是在 startRecord 前调用 CameraContext.setZoom 强制切换编码格式,但更简单的做法是让用户升级微信版本。

2. 华为P系列录像时画面闪烁
这是由于相机自动对焦导致的。可以在Camera组件上加 focus-distance="100" 固定焦距,或者用 flash="off" 关闭闪光灯。实测设置 auto-focus="false" 后闪烁消失。

3. 小米手机录像文件损坏
小米部分机型(如Redmi Note 10)在录像过程中如果切换前后摄像头,会导致文件无法播放。解决方案是禁止用户录像时切换摄像头,或者在切换前先停止录像。

六、进阶:录像与后台状态管理

小程序切到后台时,录像会自动停止。但用户可能有“录到一半接电话”的场景。你可以用 onHide 生命周期监听,在切后台时保存当前录像状态,返回时恢复。但注意,Camera组件在后台会被销毁,恢复时需要重新创建。

这里有个取巧的办法:用 wx.setScreenBrightness 保持屏幕常亮,减少用户切后台的概率。同时,在 onShow 里检查是否有未完成的录像,提示用户继续或放弃。

代码示例:

onHide() {
  if (this.data.isRecording) {
    wx.setStorageSync('pendingRecord', true);
    this.stopRecord(); // 自动停止并保存临时文件
  }
},
onShow() {
  const pending = wx.getStorageSync('pendingRecord');
  if (pending) {
    wx.showModal({
      title: '检测到未完成的录像',
      content: '是否继续刚才的录像?',
      success: (res) => {
        if (res.confirm) {
          // 继续录像,但需要重新创建Camera组件
          this.startRecord();
        }
        wx.removeStorageSync('pendingRecord');
      }
    });
  }
}

录像功能看起来简单,但真正做好,需要兼顾权限、兼容性、用户体验和异常处理。上面这些细节,是我在多个小程序项目中踩坑后总结出来的。如果你在开发中遇到其他奇怪的问题,欢迎交流——毕竟,微信小程序的坑,总是比文档里写的多那么几个。

上一篇
认证这道坎:小程序上线前,你被“官方验证”卡过几次?
下一篇
南宁图形开发怎么做?南宁图形开发公司哪家好