录屏代码,录制游戏内音频视频,生成webm视频

测试了2.4.x 3.x暂时无法完美实现,因为 AudioContext在3.0闭包内,外面无法获取

const { ccclass, property } = cc._decorator;
@ccclass
export default class Screencap extends cc.Component {
    onLoad(): void {
        //获取视频通道
        var videoStream = cc.game.canvas.captureStream();
        //获取cocos音频解析AudioContext
        var context = cc.sys["__audioSupport"].context
        //创建音频通道
        var audioSteramNode = context.createMediaStreamDestination();
        //修改 AudioContext createBufferSource 原型链 把创建的 AudioBufferSourceNode 连接 音频通道
        const createBufferSource = AudioContext.prototype.createBufferSource;
        AudioContext.prototype["_createBufferSource"] = createBufferSource;
        AudioContext.prototype["createBufferSource"] = function () {
            var _currentSource = this["_createBufferSource"]();
            _currentSource.connect(audioSteramNode);
            return _currentSource;
        }
        // 创建一个0赫兹的音效,防止 没有声音录制失败  0.1秒后停止声音 
        var oscillator = context.createOscillator();
        oscillator.type = "square";
        oscillator.frequency.value = 0;
        oscillator.connect(context.destination);
        oscillator.connect(audioSteramNode);
        oscillator.start();
        oscillator.stop(context.currentTime + 0.1);

        //添加音频track到视频通道
        videoStream.addTrack(audioSteramNode.stream.getAudioTracks()[0]);
        //获取支持录制的格式
        var getSupportedMimeTypes = function () {
            const VIDEO_TYPES = [
                "webm",
                "mp4",
                "ogg",
                "x-matroska",
            ];
            const VIDEO_CODECS = [
                "vp9",
                "vp9.0",
                "vp8",
                "vp8.0",
                "h265",
                "h.265",
                "h264",
                "h.264",
                "avc1",
                "av1",
                "opus",
            ];

            const supportedTypes = [];
            VIDEO_TYPES.forEach((videoType) => {
                const type = `video/${videoType}`;
                VIDEO_CODECS.forEach((codec) => {
                    const variations = [
                        `${type};codecs=${codec}`,
                        `${type};codecs:${codec}`,
                        `${type};codecs=${codec.toUpperCase()}`,
                        `${type};codecs:${codec.toUpperCase()}`,
                        `${type}`
                    ]
                    variations.forEach(variation => {
                        if (MediaRecorder.isTypeSupported(variation))
                            supportedTypes.push(variation);
                    })
                });
            });
            return supportedTypes;
        }
        const supportedMimeTypes = getSupportedMimeTypes();
        //创建录制程序
        var mediaRecorder = new MediaRecorder(videoStream, { mimeType: supportedMimeTypes[0] });

        var chunks = [];
        mediaRecorder.addEventListener('dataavailable', (e) => {
            chunks.push(e.data)
        })
        // 监听停止保存视频
        mediaRecorder.addEventListener('stop', function () {
            var blob = new Blob(chunks, { type: chunks[0].type });
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.download = 'video.webm';
            a.click();
        })
        //监听浏览器后台,暂停游戏
        document.addEventListener('visibilitychange', () => {
            if (document.visibilityState === "hidden") {
                console.log('当前页签隐藏,即打开新页签')
                cc.game.pause();
                mediaRecorder.pause();
            }
            if (document.visibilityState === "visible") {
                console.log('当前页签显示,即打开当前页签')
                cc.game.resume();
                // 网页重新获得焦点
                mediaRecorder.resume();
            }
        });
        //js监听键盘ctrl+s快捷键保存
        document.addEventListener('keydown', (event) => {
            if (event.ctrlKey && event.key == "s") {
                mediaRecorder.stop();
                event.preventDefault();
            }
        }, true);
        mediaRecorder.start();
    }

}
5赞

研究了一星期,网上只有录屏代码,没有录音代码,这次共享出来,希望用得着的人少走弯路。

1赞

亲测有效,大佬牛逼~~

音效这块的逻辑,全网几乎都没有,搜遍了所有的论坛,最后终于解决了,以后我也有不能解决的问题,也需要来论坛看大家怎么解决的。

这个好,我们也做了这一块东东!!!