Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

快速接入

  1. 启动应用
  1. 获取实例化参数

从弹出侧栏的“Web 直连信息”的 URL 参数中获得以下字段信息:

字段名说明
token应用唯一标识
address信令服务地址
urlICE 服务地址
  1. 使用上述信息初始化 signalingiceConfig 变量
// 所有服务的 iceConfig 配置一致consticeConfig=[{urls: `turn:${url}:3478`,// 默认端口 3478username: "coturn",// 默认用户 coturncredential: "123456",// 默认凭据 123456},];// 云游戏服务信令地址constsignaling=`wss://${address}/clientWebsocket/${token}`;// 云手机信令地址constsignaling=`wss://${address}/signaling/client/${token}`;
  1. 初始化实例

连接实例前两个参数由步骤 3 提供,hostElement 为任意固定尺寸的 HTML 元素。

不同应用类型 Launcher 不一致。若类型不匹配连接仍可建立,但事件转换会不一致导致无法交互。

// 如果启动的是 Windows 应用constlauncher=newLauncher(signaling,iceConfig,hostElement);// 如果启动的是 Android 应用constlauncher=newMobileLauncher(signaling,iceConfig,hostElement);

功能与方法

Windows 应用独有功能

虚拟键盘
// 开启launcher.showKeyboard();// 关闭launcher.hideKeyboard();
IME 键盘(手机默认输入法)
// 唤起launcher.wakeOnIME();
虚拟摇杆
// 开启launcher.showJoyStick();// 关闭launcher.hideJoyStick();
切换触控板模式
默认(不开启)

不显示指针,支持以下交互:

  • 左击(轻触)
  • 拖动
  • 右击(长按)
触控(direct 模式)

显示指针,指针跟随触点位置移动,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
拖动(relative 模式)

显示指针,指针相对触点移动偏移量变动位置,支持以下交互:

  • 左击(轻触)
  • 移动(滑动)
  • 拖动(长按滑动)
  • 右击(双击)
// 启用拖动模式launcher.enableTrackpad("relative");// 启用触控模式launcher.enableTrackpad("direct");// 禁用触控板launcher.disableTrackpad();
自定义虚拟控件布局

使用虚拟控件编辑器创建控件布局,单击“复制键盘配置”,将复制的内容赋值给 layout 变量。

// 这里作为演示只创建了一个 S 按键constlayout=[{xPercent: 0.11299435028248588,yPercent: 0.6782128514056225,widthPercent: 0.1,heightPercent: 0.17771084337349397,codes: 83,showName: "",schemeKeys: "S",aspectRatio: 1,srcList: [],type: 0,opacity: 1,anchor: "screen",},];// 创建一个虚拟控件布局,返回值为该布局的唯一标识constid=launcher.createOnScreenControlsProfile("control_name",layout);// 显示指定 id 的虚拟控件布局,参数可选,不传默认显示第一个launcher.showOnScreenControlsByProfileId(id);// 关闭launcher.hideOnScreenControls();
文件上传
// file 为浏览器 File 对象launcher.uploadFile(file,(e)=>{if(e.state==="progress"){// 发送进度 [0-100]console.log(e.progress);}elseif(e.state==="error"){// 远端拒绝接或者发送错误console.error(e.reason);}elseif(e.state==="done"){console.log("done");}});
变更编码器设定
// 修改推流端编码器的设置launcher.changeCodecOptions({bitrate: 3000,// 码率framerate: 30,// 帧率gopLength: 250,// I 帧间隔});// 如果只需改变码率launcher.changeCodecOptions({bitrate: 3000});
变更分辨率
// 修改分辨率为 HDlauncher.changeResolution(1280,720);

Android 应用独有功能

发送手机功能键
constMobileKeysKeycode{KeycodeHome: 3,// Home 键KeycodeBack: 4,// 返回键KeycodeVoiceUp: 24,// 音量 + 键KeycodeVoiceDown: 25,// 音量 - 键KeycodeAppSwitch: 187,// 应用切换键}constMobileKeysActionType{ActionDown: 0,// 按下ActionUp: 1,// 抬起}// 发送一次 Home 键单击launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionDown);launcher.sendMobileAction(MobileKeysKeycode.KeycodeHome,MobileKeysActionType.ActionUp);
变更码率
// 单位 kbpslauncher.connection.changeBandwidthByRenegotiation(1500);
变更分辨率比例
// 范围 [0-1]launcher.connection.changeMobileResolutionScale(0.5);

通用功能

放大镜
// 开启launcher.showMagnifier();// 关闭launcher.hideMagnifier();
获取统计信息
// 开关统计信息launcher.toggleStatistics();// 开启后可以通过以下方法获得统计数据window.setInterval(()=>{const{ rtt, fps, bitrate, packetLossRate, latency }=launcher.report();console.log(` FPS: ${fps} rtt: ${rtt}ms latency: ${latency}ms biterate: ${bitrate}kbps packetLossRate: ${(packetLossRate*100).toFixed(3)}% `);},1000);

主要字段说明:

  • fps: 帧数
  • latency: 客户端与节点端服务之间往返时间,单位 ms
  • rtt: 客户端与 ICE 服务器之间往返时间,单位 ms
  • packetLossRate: 丢包率
  • bitrate: 视频流码率,单位 kbps

其他字段参考: Stats dictionaries

导出日志
launcher.exportLog();
销毁
launcher.destory();

实例化参数说明

// Windows 应用newLauncher(url,iceServers,hostElement[,options])// Android 应用newMobileLauncher(url,iceServers,hostElement[,options])
必填参数说明
字段类型说明
urlstring最终的信令 URL,参照快速接入
iceServersRTCIceServer[]ICE 服务配置,参照快速接入
hostElementHTMLElement任意固定尺寸的 HTML 元素
可选参数 options 包含字段及其说明
字段类型默认值说明
autorunRivatunerbooleanfalse是否自动开启数据统计
orientationLockbooleanfalse开启后流内容不再自动旋转
enableControlPanelbooleanfalse是否开启默认的控制面板
themeColorstring'ff0000'虚拟控件(如果有)的主题色
onPhaseChange(phase: Phase, deltaTime: number) => voidnoop每当阶段变化会产生一次事件,参数二为两次事件的间隔,详见 Phase 说明
Launcher 独有的可选参数
字段类型默认值说明
disableFileTransferbooleanfalse是否拒绝接收远端推送的文件
disablePointerManagerbooleanfalse是否禁用指针样式同步
disablePointerLockbooleanfalse是否禁用指针锁定(即使没有指针也不进入相对移动模式)
enableClipboardbooleanfalse是否开启剪贴板同步
useClassicEventbooleanfalse是否使用 mouseevent 替代 pointerevent 作为指针事件
Phase 说明
阶段说明
initial初始阶段,刚实例化后或断网重连后进入该阶段
signaling-connected浏览器端与信令建立连接成功,该阶段能响应信令消息
node-ready节点与信令建立连接成功,标志着浏览器端可以开始与推流端交换候选
end-candidate交换候选结束
peer-connection-connectedWebRTC 连接建立成功
bandwidth-detect如果开启了自动测速,会有这个阶段以检测带宽
data-channel-open数据通道打开,标志着可以进行交互
loaded-metadata视频流开始播放

事件

如需自行处理一些流程,可以通过 launcher.connection.event.[eventName].[on|off|once|emit] 进行交互。

event name发送时间点/说明payload
connect收到信令的 connect 事件时ConnectMSG
afk收到信令的 operateOverTime 事件时number
open与信令的 WebSocket 连接建立成功后Event
close与信令的 WebSocket 连接关闭后CloseEvent
queue收到信令的 queue 事件时number
ready收到信令的 ready 事件时ReadyMSG
endCandidate连接双方完成 ICE 候选地址的交换时RTCPeerConnectionIceEvent
cursor推流端光标有变化时Cursor
hangUp当推流端与信令失联时void
disconnect收到信令的 peerDisconnected 事件或 WebSocket 链接断开始时string
receivedLink推流端捕获到超链接时string
receivedTrack实例接收到媒体轨道时;payload 为该轨道MediaStreamTrack
dataChannelConnectedDataChannel 实例打开时;当收到该事件时说明可以开始交互Event
interaction推流端运行的应用利用 socket 发送事件时string | ArrayBuffer
kick收到信令的 kick 事件时string
networkChangedPeerConnection 检测到网络变化时string
echo收到响应的 echo 消息时;payload 为该次往返时间number
screenshot完整接收完截图数据时;payload 为截图数据Blob
screenshotData收到截图数据时;payload 为数据字节长度number
kickOut收到踢人消息时string
clipboard完整接收完剪贴板数据时;payload 为剪贴板数据string | Blob
encodeSettings收到视频编码配置时{ framerate: number; bitrate: number; gopLength: number }
mobileResolutionInfo收到 Android 的分辨率数据时{ width: number; height: number; scale: number }
resolutionInfo收到 Windows/Linux 的分辨率数据时[number, number, number][]

建议兼容性使用

桌面端
FeatureChromeEdgeFirefoxOperaSafari
最低需求6479695813.1
支持所有特性7179696313.1
移动端
FeatureChrome AndroidFirefox for AndroidOpera AndroidSafari on iOSSamsung InternetWebView Android
最低需求64794713.49.064
支持所有特性84795013.410.084

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages