// 初始化音视频流
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}` });
}
}
- 发布:2025-11-19 15:12
- 更新:2025-11-19 15:12
- 阅读:55
产品分类: uniapp/App
PC开发环境操作系统: Mac
PC开发环境操作系统版本号: Apple M2;MacOS 14.5 (23F79)
手机系统: Android
手机系统版本号: Android 14
手机厂商: 荣耀400pro
手机机型: 荣耀400pro
页面类型: vue
vue版本: vue3
打包方式: 云端
项目创建方式: CLI
CLI版本号: 4.36
示例代码:
操作步骤:
vue页面使用 renderjs, 然后MediaRecorder开始录制和结束录制,然后使用video播放视频
vue页面使用 renderjs, 然后MediaRecorder开始录制和结束录制,然后使用video播放视频
预期结果:
renderjs 使用录像结束之后,需要能正常播放录制后的视频
renderjs 使用录像结束之后,需要能正常播放录制后的视频
实际结果:
renderjs 使用录像结束之后,无法正常播放录制后的视频
renderjs 使用录像结束之后,无法正常播放录制后的视频
bug描述:
uniapp 使用renderjs 和 webview两种方式在app,使用MediaRecorder 录像,结束录像之后,renderjs无法播放视频;webview 用同样的方式录像之后,能正常播放;但是普通vue页面使用webview又会全屏,nvue页面限制太多,不能用这个nvue
所以有办法让renderjs 录像结束之后,正常播放视频?
0 个回复