本文实现字节小游戏的录屏分享以及录屏播放功能(cocoscreator 2.4.x)
官方文档: 字节小游戏文档
项目地址: git地址
- 效果演示

演示中主要分2个功能。其一是游戏录屏,二是录屏播放。
游戏录屏
export class byteDanceManager {
private static _instance = null;
static instance(): byteDanceManager {
if(!byteDanceManager._instance) {
byteDanceManager._instance = new byteDanceManager();
}
return byteDanceManager._instance;
}
tt: any = null;
videoHasStop: boolean = false;
videoHasEnd: boolean = false;
private gameRecorder: any = null;
private totalRecord: number = 300;
private recordTime: number = 0;
private recordTimer: any = null;
private videoPath: string = '';
private recentAdTime: Date = new Date();
init() {
this.tt = window["tt"];
}
shareGame() {
}
shareAppFunc(title: string, image: string, onSuccess: Function, onFail: Function){
this.tt.shareAppMessage({
title: title,
imageUrl: image,
success: () => {
onSuccess && onSuccess();
},
fail: (e) => {
onFail && onFail();
}
})
}
shareRecordVideo(title: string, videoPath: string, onSuccess: Function, onFail: Function) {
this.tt.shareAppMessage({
title: title,
channel: "video",
extra: {
videoTopics: [],
hashtag_list: [],
videoPath: videoPath,
withVideoId: true,
},
success: (res) => {
onSuccess && onSuccess();
},
fail: (e) => {
if(this.checkAppName()){
onSuccess && onSuccess();
}else{
onFail && onFail();
}
}
})
}
private checkAppName(){
let result = false;
this.tt.getSystemInfo({
success: (res) => {
if(res.platform === 'ios' && res.appName === 'Toutiao'){
result = true
}
},
fail: (e) => {
console.log("getSystemInfo fail: ", e);
}
})
return result;
}
startRecord(callback: Function){
if(!this.tt) {
callback && callback();
return;
}
if(!this.gameRecorder){
this.gameRecorder = this.tt.getGameRecorderManager();
}
this.videoHasEnd = false;
this.videoHasStop = false;
this.gameRecorder.start({duration: this.totalRecord});
this.gameRecorder.onStart(() => {
this.recordTime = 0;
this.recordTimer = setInterval(() => {
this.recordTime++;
}, 1000);
callback && callback();
});
this.gameRecorder.onResume(() => {
this.recordTimer = setInterval(() => {
this.recordTime++;
}, 1000)
});
this.gameRecorder.onPause(() => {
clearInterval(this.recordTimer);
});
this.gameRecorder.onStop((res) => {
this.videoHasEnd = true;
this.videoPath = res.videoPath;
console.log("this.videoPath:", this.videoPath);
clearInterval(this.recordTimer);
this.recordTime = 0;
});
this.gameRecorder.onError((e) => {
console.log("gameRecord error: ", e);
})
}
resumeRecord(callback: Function){
if(!this.tt) {
return;
}
if(!this.gameRecorder){
console.log("gameRecorder is null, resumeRecord fail");
}else{
this.gameRecorder.resume();
callback && callback();
}
}
pauseRecord(callback: Function){
if(!this.tt) {
return;
}
if(!this.gameRecorder){
console.log("gameRecorder is null, pauseRecord fail");
}else{
this.gameRecorder.pause();
callback && callback();
}
}
stopRecord(callback: Function){
if(!this.tt) {
return;
}
if(!this.gameRecorder){
console.log("gameRecorder is null, stopRecord fail")
}else{
this.gameRecorder.stop();
callback && callback();
}
}
getVideoPath(){
return this.videoPath;
}
public onShareFunc(text: string, image: string, callback: Function){
let channel = "";
this.tt.getSystemInfo({
success: (res) => {
console.log("getSystemInfo success: ", res);
if (res.appName === 'Douyin') {
channel = "invite";
} else if(res.appName === 'Toutiao'){
channel = 'article';
} else {
channel = '';
}
},
fail: (res) => {
console.log("getSystemInfo fail: ", res);
channel = '';
}
})
this.tt.shareAppMessage({
title: text,
channel: channel,
imageUrl: image,
success: ()=>{
callback && callback();
},
fail: ()=>{
callback && callback();
},
complete: ()=>{
}
})
}
}
export const btMgr = byteDanceManager.instance();
btMgr.startRecord(()=>{})
btMgr.stopRecord(()=>{})
录屏播放
- 录屏播放需要在录屏停止后,从录屏停止监听中获得录屏资源地址,使用字节的离屏video渲染出来。
- 代码内容
let videoPath = btMgr.getVideoPath();
const {ccclass, property} = cc._decorator;
@ccclass
export default class ShareVideo extends cc.Component {
@property(cc.Node)
private parentNode: cc.Node = null;
private cameraNode;
private video;
private videoTexture: cc.Texture2D;
start () {
}
initVideo(video: string){
this.showcamera(video);
}
private showcamera(video: string) {
this.cameraNode = new cc.Node();
this.cameraNode.width = this.parentNode.width;
this.cameraNode.height = this.parentNode.height;
this.cameraNode.addComponent(cc.Sprite)
this.parentNode.addChild(this.cameraNode);
if (typeof window['tt'] !== 'undefined') {
this.playVideo(video);
}
}
private playVideo(video: string) {
this.video = window['tt'].createOffscreenVideo();
this.video.src = video;
this.video.onCanplay(() => {
if(this.node && this.node.isValid){
this.video.play();
this.videoTexture = new cc.Texture2D();
this.videoTexture.initWithElement(this.video);
this.videoTexture.handleLoadedTexture();
this.cameraNode.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(this.videoTexture);
this.cameraNode.width = this.parentNode.width;
this.cameraNode.height = this.parentNode.height;
}
});
this.video.onCandraw(()=>{
})
this.video.onPlay(()=>{
console.log("开始录屏");
});
this.video.onEnded(()=>{
});
this.video.onPause(()=>{
});
}
update(dt) {
if (this.video && this.videoTexture) {
this.videoTexture.update({
image: this.video,
flipY: false
});
}
}
}
到这里基本就完成了录屏和录屏播放的功能了。已经可以打包到字节平台调试,如果要录屏分享可以自接调用btMgr.shareRecordVideo()方法并传入相关参数即可。注意录屏以及播放功能,只能使用真机调试。