菜菜2
菜菜2
  • 发布:2025-11-19 15:12
  • 更新:2025-11-19 15:12
  • 阅读:55

【报Bug】uniapp 使用renderjs 和 webview两种方式在app,开始录像和结束录制之后,renderjs方式的无法播放视频

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Mac

PC开发环境操作系统版本号: Apple M2;MacOS 14.5 (23F79)

手机系统: Android

手机系统版本号: Android 14

手机厂商: 荣耀400pro

手机机型: 荣耀400pro

页面类型: vue

vue版本: vue3

打包方式: 云端

项目创建方式: CLI

CLI版本号: 4.36

示例代码:

// 初始化音视频流  
  async initMediaStream() {  
    try {  
      navigator.mediaDevices.getMedia = navigator.mediaDevices.getUserMedia || navigator.mediaDevices.webkitGetUserMedia || navigator.mediaDevices.mozGetUserMedia || navigator.mediaDevices.msGetUserMedia;  

      this.mediaStream = await navigator.mediaDevices.getMedia({  
        video: { width: 1280, height: 720, frameRate: {  min: 30, ideal: 60, max: 60  } },  
        audio: true,  
      });  
      // const previewVideo = document.createElement('video');  
      // previewVideo.src = URL.createObjectURL(this.mediaStream);  
      // // previewVideo.play();  
      // this.logMessage('stream_init', '音视频流初始化成功');  
      // // 创建临时 video 元素并添加到页面(仅验证用)  
      const previewVideo = document.createElement('video');  
      previewVideo.srcObject = this.mediaStream;  
      previewVideo.autoplay = true;  
      previewVideo.muted = true; // 避免回声  
      previewVideo.style.position = 'fixed';  
      previewVideo.style.top = '0';  
      previewVideo.style.width = '200px';  
      previewVideo.style.height = '200px';  

      previewVideo.style.border = '2px solid yellow';  
      document.body.appendChild(previewVideo);  
      return true;  
    } catch (e) {  
      this.onError({ msg: `音视频流获取失败:${e.message}` });  
      return false;  
    }  
  }  

  // 开始录像  
  async startRecording() {  
    if (this.isRecording) return;  
    const streamReady = await this.initMediaStream();  
    if (!streamReady) return;  

    try {  
      const options = {  
        mimeType: 'video/webm; codecs=vp8,opus',  
        audioBitsPerSecond: 128000,  
        videoBitsPerSecond: 2500000  
      };  
      const support = typeof MediaRecorder !== 'undefined'  

      console.log('MediaRecorder 支持吗?', support)  

      this.mediaRecorder = new MediaRecorder(this.mediaStream, options);  
      this.chunks = [];  
      this.uploadChunks = [];  

      this.mediaRecorder.ondataavailable = (e) => {  
        if (e.data.size > 0) {  
          this.chunks.push(e.data);  
          this.uploadChunks.push(e.data);  
        }    
      };  

      this.mediaRecorder.onstop = () => this.handleRecordingStop();  
      this.mediaRecorder.start();  
      this.isRecording = true;  

      // 定时上传分片(每2秒)  
      this.uploadInterval = setInterval(() => this.uploadVideoChunk(), 2000);  
      this.logMessage('record_start', '开始录像');  
    } catch (e) {  
      this.onError({ msg: `录像启动失败:${e.message}` });  
    }  
  }  

  // 停止录像  
  stopRecording() {  
    if (!this.isRecording) return;  
    this.mediaRecorder.stop();  
    clearInterval(this.uploadInterval);  
    this.isRecording = false;  
    this.logMessage('record_stop', '停止录像');  

    // 上传最后分片并通知合并  
    setTimeout(() => {  
      this.uploadVideoChunk();  
      this.notifyBackendMerge();  
    }, 1000);  

    // 释放流  
    this.mediaStream.getTracks().forEach(track => track.stop());  
  }  

  // 处理录像结束  
  handleRecordingStop() {  
    const videoBlob = new Blob(this.chunks, { type: 'video/webm' });  
    const url = URL.createObjectURL(videoBlob)  

    // 把视频URL回传给Vue页面  
    this.saveVideoToLocal({ url })  
    this.logMessage('record_complete', `录像生成成功(${(videoBlob.size / 1024 / 1024).toFixed(2)}MB)`);  
    console.log('录像Blob大小:', videoBlob.size); // 正常应大于0  
    console.log('录像MIME类型:', videoBlob.type); // 应为 video/webm  

    // 显示视频预览  
    try {   
      const videoView = document.getElementById('videoView');  
    if (videoView) {  
      videoView.src = URL.createObjectURL(videoBlob);  
      console.log('视频预览URL:', videoView.src); // 应为 blob:xxx 格式  
      videoView.style.display = 'block';  
      videoView.style.border = '1px solid red';  
      videoView.autoplay = true;  
      document.getElementById('photoView').style.display = 'none';  
      videoView.onerror = (error) => {  
        console.error('录像预览失败:', error);  
        this.onError({ msg: `录像预览失败:${error || error.message}` });  
      };  
    }  
    } catch (e) {  
      this.onError({ msg: `录像预览失败:${e.message}` });  
    }  
  }  

操作步骤:

vue页面使用 renderjs, 然后MediaRecorder开始录制和结束录制,然后使用video播放视频

预期结果:

renderjs 使用录像结束之后,需要能正常播放录制后的视频

实际结果:

renderjs 使用录像结束之后,无法正常播放录制后的视频

bug描述:

uniapp 使用renderjs 和 webview两种方式在app,使用MediaRecorder 录像,结束录像之后,renderjs无法播放视频;webview 用同样的方式录像之后,能正常播放;但是普通vue页面使用webview又会全屏,nvue页面限制太多,不能用这个nvue

所以有办法让renderjs 录像结束之后,正常播放视频?

2025-11-19 15:12 负责人:无 分享
已邀请:

要回复问题请先登录注册