ray-streaming
RayStreaming SDK for Web
Guides
Quick start
see live-cat or live-dragon or live-qjc
Example
File transfer
connection.event.fileTransferApply.on((request) => {
connection.replyFileTransferApply(request.fileUnique, allowed)
})
connection.event.receivedFile.on((file) => console.log(file.data, file.name))
connection.sendFile(file, (e) => {
if (e.state === 'queue') {
console.log('queue')
} else if (e.state === 'progress') {
console.log(e.progress)
} else if (e.state === 'error') {
console.error(e.reason)
} else if (e.state === 'done') {
console.log('done')
}
})
API reference
Connection
Manage the Signaling and PeerConnection connection with node machine
new Connection(url, iceServers[, iceTransportPolicy][, minBitrate][, maxBitrate][, startBitrate][, enableAFK]))
url
<string> signaling endpointiceServers
<RTCIceServer[]> RTCIceServericeTransportPolicy
<RTCIceTransportPolicy> iceTransportPolicy Default: 'all'
minBitrate
<number> append x-google-min-bitrate in create offer Default: 2000maxBitrate
<number> x-google-max-bitrate Default: 5000startBitrate
<number> x-google-start-bitrate Default: 4000enableAFK
<boolean> disconnect when detecting user away from keyboard if true Default: true
connection.emitUIInteraction(msg)
Send UI interaction message to remote application
connection.emitUIInteraction(JSON.stringify({ eventName: 'A' })).then((result) => {
if (result) {
console.log('execute success')
}
})
connection.screenshot([params])
params
<Object>
index
<number> screen index Default: 0left
<number> x coordinate origin Default: 0top
<number> y coordinate origin Default: 0width
<number> width of screenshot Default: 1920height
<number> height of screenshot Default: 1080
screenshot origin stream
connection.clipboard(text)
text
<string> string from clipboard
sync clipboard text to node
connection.changeBandwidth(bandwidth)
change bandwidth with fixed bitrate
connection.changeBandwidth(startBitrate, maxBitrate, minBitrate)
startBitrate
<number> kbpsmaxBitrate
<number> kbpsminBitrate
<number> kbps
change bandwidth with bitrate range
connection.destroy()
Close all connect, off event listener
connection.sendFile(file, [onStateChange])
file
<File>onStateChange
<StateChangeHandler>
upload file to remote node
Player
Provide the container to play the remote stream,
new Player(hostElement[, onPlay][, voicedAtPlay][, orientationLock])
hostElement
<HTMLElement> any block element with fixed sizeonPlay
<() => void> invoke when video playvoicedAtPlay
<boolean> remove muted attribute when play if set true Default: true
orientationLock
<boolean> video will rotate to screen orientation with the same aspect ratio if set false Default: true
onRotate
<(r: boolean) => void> call when hostElement resize or video track resolution change
player.resizePlayer()
Resize player style to fill host element if host element size is smaller than player or resize player style to actual size
player.showTextOverlay(text)
Show prompt with specify text and mask video stream
player.destroy()
Remove created elements
RunningState
State of the remote node or front-end widget, manager by launcher or execution context
const runningInfo = new RunningState()
Helper
Helper.createDefaultEventStream(target, runningInfo)
target
<HTMLVideoElement> the video elementrunningInfo
<RunningState> RunningState instance
Create default stream for basic interaction, transform to ArrayBuffer from the event-adapter definition
Helper.createGamepadStream()
Create stream for gamepad, transform to ArrayBuffer from the event-adapter definition
Helper.createKeyboardStream(target[, filterKeys])
target
<HTMLVideoElement> the video elementfilterKeys
<string[]> block specify key Default: []
Create stream for keyboard, transform to ArrayBuffer from the event-adapter definition
Helper.createClipboardStream(target)
target
<HTMLVideoElement> the video element
listen target's focus event and transform to clipboard text
Helper.attachListener(target, runningInfo, connection[, options])
target
<HTMLVideoElement>runningInfo
<RunningState>connection
<Connection>options
<Object>
enableGamepad
<boolean> create gamepad event by default Default: falseenableClipboard
<boolean> create clipboard event by default Default: falsefilterKeys
<string[]> block specify key Default: []
the default behavior for consuming the event stream
Rivatuner
use getStats
to gather statistics from provided Connection
new Rivatuner()
rivatuner.offer(connection)
connection
<Connection> Connection instance
Provide Connection
rivatuner.scan()
Start timer
rivatuner.stop()
Stop timer
rivatuner.toggle()
Toggle scan or stop
rivatuner.report()
- Returns: <Object>
- fps: <number>
- latency: <number> ms
- bitrate: <number> kbs
- packetLossRate: <number>
- averageJitterBufferDelay: <number> ms
- framesReceived <number>
- framesDecoded <number>
- keyFramesDecoded <number>
- framesDropped <number>
- framesPerSecond <number>
Report current statistics
rivatuner.destroy()
Release listener
Dashboard
use Dashboard
to count network-related information and custom information which has to use Rivatuner if using default dashboard.
new Dashboard(hostElement, fieldsGroups, dashboardState)
hostElement
<HTMLElement>fieldsGroups
Array of objects that each object is a graphdashboardState
offer a default config to Dashboard
Dashboard.createDefaultDashboard(hostElement)
new DashboardConfig(options?: Partial<Options>)
options
Setting default configs to Dashboard.
interface Options {
xCount: number
yCount: number
dataCount: number
paddingLeft: number
paddingRight: number
paddingTop: number
paddingBottom: number
xAxisGap: number
legendRadius: number
themeColor: string
}
import { Dashboard, DashboardConfig, Rivatuner } from 'ray-streaming'
const rivatuner = new Rivatuner()
const dashboard = Dashboard.createDefaultDashboard(hostElement)
setInterval(() => {
const { fps, ...rest } = rivatuner.report()
dashboard.insert({
...rest,
framesPerSecond: fps,
})
}, 500)
let p = window.performance
const dashboard = Dashboard.createDefaultDashboard(hostElement, [
{
totalJSHeapSize: '',
usedJSHeapSize: '',
jsHeapSizeLimit: '',
},
{
delay: 'ms',
},
])
setInterval(() => {
const { fps, ...rest } = rivatuner.report()
dashboard.insert({
...rest,
framesPerSecond: fps,
totalJSHeapSize: p.memory?.totalJSHeapSize ?? 0,
usedJSHeapSize: p.memory?.usedJSHeapSize ?? 0,
jsHeapSizeLimit: p.memory?.jsHeapSizeLimit ?? 0,
delay: calculatedDelay ?? 0,
})
}, 500)
const dashboard = new Dashboard(
hostElement,
[
{
totalJSHeapSize: '',
usedJSHeapSize: '',
jsHeapSizeLimit: '',
delay: 'ms',
},
],
new DashboardConfig(),
)
setInterval(() => {
dashboard.insert({
totalJSHeapSize: p.memory?.totalJSHeapSize ?? 0,
usedJSHeapSize: p.memory?.usedJSHeapSize ?? 0,
jsHeapSizeLimit: p.memory?.jsHeapSizeLimit ?? 0,
delay: calculatedDelay ?? 0,
})
}, 500)
Caveat
- Need to initialize
Player
after WeixinJSBridgeReady
event fired if use in WeChat web-view
if (navigator.userAgent.includes('miniProgram') || navigator.userAgent.includes('MicroMessenger')) {
document.addEventListener('WeixinJSBridgeReady', () => {
})
}