js录制本地摄像头下载mp4和转file文件流

前端获取本地摄像头和麦克风并录制为mp4导出其实很简单,只是可能你不太了解相关的知识点,我已经在项目中实战过。

前端获取本地摄像头麦克风,并录制视频
export class VideoRecording { // 录视频
    mediaRecorder: MediaRecorder | null;
    stream: MediaStream | null;
    chunks: any[];
    endCallback: any[];
    constructor() {
        this.mediaRecorder = null; // 录音对象
        this.stream = null; // 轨道
        this.chunks = []; // 录制缓存
        this.endCallback = []; // 结束回调
    }
    create() { // 创建一个录制任务
        return new Promise((resolve, reject) => {
            this.resetState();
            navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream) => {
                this.stream = stream;
                const mime = MediaRecorder.isTypeSupported("video/webm\;codecs=h264") ? "video/webm\;codecs=h264" : "video/webm";
                this.mediaRecorder = new MediaRecorder(stream, { mimeType: mime });
                resolve({format: mime === "video/webm;codecs=h264" ? 'mp4': 'webm'});
            }).catch((err) => {
                reject(err);
            });
        });
    }
    start() { // 开始
        return new Promise((resolve, reject) => {
            this.judgeMediaRecorderIs().then((mediaRecorder: MediaRecorder) => {
                mediaRecorder.start();
                mediaRecorder.addEventListener('dataavailable', (e) => {
                    this.chunks.push(e.data);
                    this.endCallback.forEach((resolve) => {
                        resolve();
                        this.endCallback.shift();
                    });
                });
                resolve('');
            }).catch((err) => {
                reject(err);
            });
        });
    }
    stop() { // 结束
        return new Promise((resolve, reject) => {
            this.judgeMediaRecorderIs().then((mediaRecorder: MediaRecorder) => {
                if (mediaRecorder.state === 'inactive') {
                    return reject({code: 0, message: '已结束'});
                };
                mediaRecorder.stop();
                this.stream.getTracks().forEach((track) => { track.stop(); })
                this.endCallback.push(resolve);
            }).catch((err) => {
                reject(err);
            });
        });
    }
    download() { // 下载
        return new Promise((resolve, reject) => {
            this.handleChunksToBolb().then((blob: Blob) => {
                let url = URL.createObjectURL(blob);
                let a = document.createElement('a');
                a.href = url;
                a.download = MediaRecorder.isTypeSupported("video/webm\;codecs=h264") ? 'video.mp4' : 'video.webm';
                a.click();
                resolve(url);
            }).catch((err) => {
                reject(err);
            });
        });
    }
    viewRecording() { // 获取本地播放url
        return new Promise((resolve, reject) => {
            this.handleChunksToBolb().then((blob: Blob) => {
                let url = URL.createObjectURL(blob);
                resolve(url);
            }).catch((err) => {
                reject(err);
            });
        });
    }
    toFile() { // 录音缓存转file
        return new Promise((resolve, reject) => {
            this.handleChunksToBolb().then((blob: Blob) => {
                let filename = MediaRecorder.isTypeSupported("video/webm\;codecs=h264") ? 'video.mp4' : 'video.webm';
                let fileType = filename.includes('.mp4') ? 'video/mp4' : 'video/webm';
                resolve(new File([blob], filename, { type: fileType }));
            }).catch((err) => {
                reject(err);
            });
        });
    }
    handleChunksToBolb() { // 录音缓存转bolb
        return new Promise((resolve, reject) => {
            this.judgeChunksIs().then((chunks: any) => {
                let blob = new Blob(chunks, { type: MediaRecorder.isTypeSupported("video/webm\;codecs=h264") ? 'video/mp4' : chunks[0].type })
                resolve(blob);
            }).catch((err) => {
                reject(err);
            });
        });
    }
    judgeChunksIs() { // 判断是否有录音缓存
        return new Promise((resolve, reject) => {
            let chunks = this.chunks;
            if (chunks.length === 0) {
                return reject({code: 0, message: '没有录制的缓冲'});
            };
            return resolve(chunks);
        });
    }
    judgeMediaRecorderIs() { // 判断是否创建录制任务
        return new Promise((resolve, reject) => {
            let mediaRecorder = this.mediaRecorder;
            if (!mediaRecorder) { return reject({code: 0, message: '请先创建一个录制对象'}); };
            resolve(mediaRecorder);
        });
    }
    setEndCallback(callback) { // 存录音结束回调
        this.endCallback.push(callback);
    }
    resetState() { // 重置状态
        this.chunks = [];
        this.mediaRecorder = null;
        this.stream = null;
    }
};
实用方法
let myVideoRecording = new VideoRecording();
@params res: {
    format: 'mp4',  type: String; value: 'mp4' | 'webm'; 说明:当前支持的录制格式;
}
myVideoRecording.create().then((res: {format: 'mp4'}) => {
    // 开始录制
    myVideoRecording.start();
    // 可选择自己注册一个结束回调, 也可以调用stop()结束成功后执行下载、播放url、转file
    let endRecording = () => {
        // 下载到本地
        myVideoRecording.download();
        // 本地播放url
        myVideoRecording.viewRecording().then((srcObject) => {});
        // 转file可上传到后台服务器
        myVideoRecording.toFile().then((file) => {});
    };
    // 存结束录音回调函数
    myVideoRecording.setEndCallback(endRecording);
    // 手动结束录屏,then后才可以下载、获取本地播放url、转file对象
    myVideoRecording.stop().then(() => {
        // 下载到本地
        myVideoRecording.download();
        // 本地播放url
        myVideoRecording.viewRecording().then((srcObject) => {});
        // 转file可上传到后台服务器
        myVideoRecording.toFile().then((file) => {});
    });
});
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Java的文件输入输出(FileInputStream和FileOutputStream)来实现将本地图片文件下载。具体步骤如下: 1. 创建一个File对象,指向本地图片的路径。 ``` File file = new File("本地图片路径"); ``` 2. 创建一个FileInputStream对象,将File对象作为参数传入。 ``` FileInputStream fis = new FileInputStream(file); ``` 3. 创建一个字节数组,作为缓冲区。 ``` byte[] buffer = new byte[1024]; ``` 4. 创建一个FileOutputStream对象,将文件输出指向响应的输出。 ``` OutputStream out = response.getOutputStream(); ``` 5. 循环读取本地图片的字节,并将其写入响应的输出中。 ``` int len = 0; while ((len = fis.read(buffer)) != -1) { out.write(buffer, 0, len); } ``` 6. 关闭输入输出。 ``` fis.close(); out.flush(); out.close(); ``` 完整的代码示例: ``` @RequestMapping("/download") public void download(HttpServletResponse response) throws IOException { // 1. 创建一个File对象,指向本地图片的路径 File file = new File("本地图片路径"); // 2. 创建一个FileInputStream对象,将File对象作为参数传入 FileInputStream fis = new FileInputStream(file); // 3. 创建一个字节数组,作为缓冲区 byte[] buffer = new byte[1024]; // 4. 创建一个FileOutputStream对象,将文件输出指向响应的输出 OutputStream out = response.getOutputStream(); // 5. 循环读取本地图片的字节,并将其写入响应的输出中 int len = 0; while ((len = fis.read(buffer)) != -1) { out.write(buffer, 0, len); } // 6. 关闭输入输出 fis.close(); out.flush(); out.close(); } ``` 注意:需要替换代码中的“本地图片路径”为实际的本地图片路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值