pc端调用电脑摄像头及麦克风完成录像或录音并实现回放和上传服务器

news/2025/2/22 1:13:44/

首先定义获取媒体设备的方法

var MediaUtils = {/*** 获取用户媒体设备(处理兼容的问题)* @param videoEnable {boolean} - 是否启用摄像头* @param audioEnable {boolean} - 是否启用麦克风* @param callback {Function} - 处理回调*/getUserMedia: function (videoEnable, audioEnable, callback) {navigator.getUserMedia =navigator.getUserMedia ||navigator.webkitGetUserMedia ||navigator.mozGetUserMedia ||navigator.msGetUserMedia ||window.getUserMedia;var constraints = { video: videoEnable, audio: audioEnable };if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {callback(false, stream);})["catch"](function (err) {callback(err);});} else if (navigator.getUserMedia) {navigator.getUserMedia(constraints,function (stream) {callback(false, stream);},function (err) {callback(err);});} else {callback(new Error("Not support userMedia"));}},/*** 关闭媒体流* @param stream {MediaStream} - 需要关闭的流*/closeStream: function (stream) {if (typeof stream.stop === "function") {stream.stop();} else {let trackList = [stream.getAudioTracks(), stream.getVideoTracks()];for (let i = 0; i < trackList.length; i++) {let tracks = trackList[i];if (tracks && tracks.length > 0) {for (let j = 0; j < tracks.length; j++) {let track = tracks[j];if (typeof track.stop === "function") {track.stop();}}}}}},
};
var mediaRecorder, mediaStream, stopRecordCallback, recorderFile;

点击开启摄像头按钮或进入页面时,打开摄像头获取实时画面,注意:此处并非已经开始录像

// 调用摄像头callCamera() {let _this = this;MediaUtils.getUserMedia(true, true, function (err, stream) {if (err) {throw err;} else {// 通过 MediaRecorder 记录获取到的媒体流mediaRecorder = new MediaRecorder(stream, {mimeType: "video/webm;codecs=vp9",});mediaStream = stream;var chunks = [],startTime = 0;var video = _this.$refs.videos;video["srcObject"] = stream;video.play();// 播放实时画面mediaRecorder.ondataavailable = function (e) {mediaRecorder.blobs.push(e.data);chunks.push(e.data);};mediaRecorder.blobs = [];mediaRecorder.onstop = function (e) {recorderFile = new Blob(chunks, {type: mediaRecorder.mimeType,});console.log(recorderFile);var url = URL.createObjectURL(recorderFile);var videosreplay = _this.$refs.videosreplay;videosreplay.setAttribute("src", url);chunks = [];if (null != stopRecordCallback) {stopRecordCallback();}};}});},

点击开始录像时开启recorder,或结束录像

record() {if (this.recordtype == "ING") {this.stopRecord(() => {console.log("结束录制");});}if (this.recordtype == "BEGIN") {this.startAudio();mediaRecorder.start();this.recordtype = "ING";}},// 对录像时长进行记录
startAudio() {this.timer = setInterval(() => {this.recordtime += 1000;if (this.recordtime == 60000) {this.stopRecord();}this.second++;if (this.second >= 60) {this.second = 0;this.minute = this.minute + 1;}if (this.minute >= 60) {this.minute = 0;this.hour = this.hour + 1;}}, 1000);},// 停止录像时终止录制器,关闭媒体流并清除时长记录定时器
stopRecord(callback) {this.recordtype = "END";this.showReplay = true;stopRecordCallback = callback;clearInterval(this.timer);// 终止录制器mediaRecorder.stop();// 关闭媒体流MediaUtils.closeStream(mediaStream);var videosreplay = this.$refs.videosreplay;videosreplay.onended = () => {this.playtime = 0;this.replayVideo = false;clearInterval(this.playtimer);};videosreplay.onclick = () => {this.showReplay = !this.showReplay;};},

录制完成后,在页面中显示回放画面,可以直接播放本地录制的流文件,也可以上传服务器后播放服务器返回的文件地址。此处要注意的是,播放回放的容器与录制画面的容器不能是同一个,否则会导致录制失败,而两个容易也不能用v-if控制,否则在录制完成后会提示找不到播放容器

<videostyle="position:absolute;":style="recordtype=='END'?'z-index:3':'z-index:1'"id="videosreplay"class="local-video"src=""ref="videosreplay"></video><videoid="video"class="local-video"autoplayref="videos"></video><div@click="toggleReplayVideo"v-if="recordtype=='END'&&showReplay"style="position:absolute;z-index:3;"><imgv-if="!replayVideo"src="~assets/image/audiorecord/video-replay.png"style="width:224rem;height:224rem;"alt=""><imgv-if="replayVideo"src="~assets/image/audiorecord/video-repause.png"style="width:224rem;height:224rem;"alt=""></div>

点击容器中的回放按钮,开始播放录制好的画面,多次点击切换播放及暂停效果。前面录制时有给播放容器设置播放结束事件,当播放完成后清除播放时长及按钮显示。

// 回放toggleReplayVideo() {this.replayVideo = !this.replayVideo;this.showReplay = false;var videosreplay = this.$refs.videosreplay;if (this.replayVideo) {videosreplay.play();this.playtimer = setInterval(() => {this.playtime += 1000;}, 1000);} else {videosreplay.pause();clearInterval(this.playtimer);}},

将录制好的视频上传到服务器

submit() {var file = new File([recorderFile],"msr-" + new Date().toISOString().replace(/:|\./g, "-") + ".mp4",{type: "video/mp4",});var formdata = new FormData();formdata.append("file", file);this.axios.post("/api/public/common/fileUpload", formdata).then((res) => {if (!res.error) {} else {this.tool.showNotify("err", res.msg);}});},

至此就完成了视频录制相关功能。

 

音频录制在结构中用到的是audio标签而不是video,并且在录制中不需要,只是在回放的时候需要,因此只需要一个容器。其余调用计算机媒体录制相关配置与调用摄像头相同,在调用getUserMedia时设置videoEnable为true,audioEnable为false

<audioid="mp3Btn"ref="audio"src=""></audio>
let audio;

点击开始录音时,调用媒体录制开始方法并计时

toggleAudio() {if (this.type == "ING") {// 结束录音this.stopRecord(() => {console.log("结束录制");});}if (this.type == "NEW") {// 开始录音this.startAudio();mediaRecorder.start();this.type = "ING";}},startAudio() {this.timer = setInterval(() => {this.recordtime += 1000;if (this.recordtime == 60000) {this.stopRecord();}this.second++;if (this.second >= 60) {this.second = 0;this.minute = this.minute + 1;}if (this.minute >= 60) {this.minute = 0;this.hour = this.hour + 1;}}, 1000);},

在录制过程中可以实现暂停录制的功能

pauseAudio() {this.audioPause = !this.audioPause;if (!this.audioPause) {this.startAudio();// 继续开始计时mediaRecorder.resume(); // 恢复录制} else {mediaRecorder.pause(); // 暂定录制clearInterval(this.timer);}},

录音结束后还需要对生成的流文件进行不同格式的转化,此处也与视频录制不同,请注意与上问视频录制中的结束函数对比

mediaRecorder.onstop = function (e) {recorderFile = new Blob(chunks, { type: "audio/mp3" });console.log(recorderFile);var url = URL.createObjectURL(recorderFile);var audio = _this.$refs.audio;audio.setAttribute("src", url);chunks = [];if (null != stopRecordCallback) {stopRecordCallback();}};

录制结束主要调用

mediaRecorder.stop();

      // 关闭媒体流

      MediaUtils.closeStream(mediaStream);

其他需要完成的也可以一并,比如清除录制时长定时器,配置音频文件播放完成成需要做的事等,可以参考视频录制结束。

回放功能也与视频回放一致,上传服务器时需要将生成的类型为mp3的流文件处理一下

submit() {var file = new File([recorderFile],"msr-" + new Date().toISOString().replace(/:|\./g, "-") + ".mp3",{type: "audio/mp3",});var formdata = new FormData();formdata.append("file", file);this.axios.post("/api/public/common/fileUpload", formdata).then((res) => {if (!res.error) {} else {this.tool.showNotify("err", res.msg);}});},

至此完成所有功能。

在视频录制及播放中可能会遇到视频录制窗口的大小与想象中配置不一样,在查阅资料中,有方法提示配置mediaRecorder.setVideoSize(717,461);两个参数代表宽高,但是在vue中好像并不生效,因此给父元素设定好对应想要的宽高后,给video元素设置object-fit: fill的样式属性即可显示满


http://www.ppmy.cn/news/900658.html

相关文章

带你【玩转Linux命令】➾ find cut 每天2个day06

带你【玩转Linux命令】➾ find & cut 每天2个day06 &#x1f53b; 一、文件管理命令1.1 find-查找文件或目录1.2 cut-指定欲显示的文件内容&#xff0c;输出到标准输出设备 &#x1f53b; 总结—温故知新 &#x1f53b; 一、文件管理命令 1.1 find-查找文件或目录 &#x…

分割时间工具

根据开始时间和结束时间 分割成若干随机时间 public static List<PullUserConfigEntity> randomDateBySize(String start,String end,int size,Long id) throws ParseException {//输入 随机起始时间//解析时间Date d1 simpleDateFormat.parse(start);long before d1.g…

【Python】pydub按一定比特率、采样率压缩音频文件

使用Python第三方库pydub按一定bitrate&#xff0c;frame_rate压缩音频文件 安装pydub pip install pydub注&#xff1a; pydub支持wav格式音频读取&#xff0c;本文处理的是MP3格式&#xff0c;所以需要安装ffmpeg. Linux下安装ffmpeg sudo apt install ffmpeg读取、压缩MP…

格式工厂 wav 比特率_鸡娃常用工具系列一格式工厂(音频转换软件)

光光发发资料已经满足不了群众的需求了&#xff0c;因为好多人发现下载的文件是M4A&#xff0c;不知道怎么办&#xff0c;倾听者又播放不了&#xff0c;干着急。 倾听者支持的格式是官方的断句音频 lis&#xff0c;mp3/wma/wav格式&#xff0c;如是其它格式识别不了。我们一般常…

音频的比特率,码率

比特率 是指 每秒传送的比特&#xff08;bit&#xff09;数。单位bps(Bit per Second),比特率越高&#xff0c;传送数据速度越快。 声音中的比特率是指将模拟声音信号转换成数字声音信号后&#xff0c;单位时间内的二进制数据量&#xff0c;是间接衡量音频质量的一个指标。 比…

FFMPEG音频视频开发: 视频转码、合并、修改分辨率、比特率

一、环境介绍 操作系统介绍:win10 64位 FFMPEG版本: 4.4.2 QT版本: 5.12.6 二、FFMPEG下载 ubuntu系统下编译安装ffmpeg: https://blog.csdn.net/xiaolong1126626497/article/details/104919095 windos系统下安装ffmpeg: https://blog.csdn.net/xiaolong1126626497/arti…

音频相关知识:声道、采样率、采样位数、样本格式、比特率

目录 声道 采样率 采样位数 帧 样本的组合方式 样本格式 比特率 采样率、采样位数、比特率三者之间的关系 参考链接&#xff1a; 声道 当人听到声音时&#xff0c;能对声源进行定位&#xff0c;那么通过在不同的位置设置声源&#xff0c;就可以造就出更好的听觉感受&…

html5 录制mp3音频,支持采样率和比特率设置

13年的时候做过html5录音,一个问题是保存的wav格式文件很大,当初用了一个迂回的方式,上传到服务器后调用 lame 编码器转换,但由于文件大,上传较慢。不得不说,前端技术发展真是日新月异,有人实现了js版本的lame编码器,可以直接在浏览器端录制MP3音频。 lamejs介绍 最初有…