Audio and Video calls made easy using Bistri Conference JS library and Bistri Signaling Server
![]() Firefox |
![]() Chrome |
![]() Safari |
![]() Edge |
![]() Opera |
|---|---|---|---|---|
| 52+ | 69+ | 11+ | 79+ | 56+ |
Include the library
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/bistri/bistri-conference-js/dist/bistri.conference-3.5.21.js">Actual Bistri Conference JS version
bc.version // 3.5.21Initialize Bistri Conference JS. Application ID and key could be retreived from your developer account https://api.developers.bistri.com/admin/applications.
We strongly recommend to set a referrer filter to prevent your application keys from being used by anybody. You can set it when editing your application parameters. Eg: my.domain.com* (don’t forget to add the wildcard suffix to match all your referrers)
bc.init( {
appId: "e3bvcx908",
appKey: "edhh64ksMpnaCcX8r29uOjH9v35",
userName: "John Doe"
} );options
- userId:
String, user id, if empty a random id is provided - userName :
String, user display name - appId:
String, application ID - appKey:
String, application key - turnServers:
Array, alternative TURN servers.[ { urls: [ "stun:stun.l.google.com:19302", "stun1.l.google.com:19302" ] } ]
- stunServers:
Array, alternative STUN servers.[ { urls: [ "turn:turn.anyfirewall.com" ], username: "webrtc", credential: "webrtc" } ]
- forceTURN:
Boolean, force connection to be relayed by TURN server (default:false) - autoCloseOnExit:
Boolean, force disconnection when closing window (default:true) - autoReconnect:
Boolean, automatically reconnect after disconnection (default:false) - autoAcceptCall:
Boolean, automatically accept incoming calls (default: true) - debug:
Boolean, show debug logs (default:false) - statsInterval:
Number, number of seconds between 2 measures, set to 0 to disable stats (default:4)
Update Bistri Conference options after init.
bc.set ( {
statsInterval: 2,
debug: true
} );Connect the JS client to the signaling server.
bc.connect ();events
Event connected is triggered when the session has been successfully opened, otherwise event error is triggered.
Disconnect the JS client from the signaling server.
bc.disconnect ();events
Event disconnected is triggered when the session has been closed.
Get client connection status.
Return a Boolean.
console.log ( bc.isConnected () );
// trueCheck if browser is compatible with Bistri Conference.
Return a Boolean.
console.log ( bc.isCompatible () );
// trueCheck if browser is compatible with screen-sharing feature.
Return a Boolean.
console.log ( bc.isScreenSharingCompatible () );
// trueGet client properties
- browser
- cpu (if available)
- device (if available)
- rendering engine
- os
Return an Object.
console.log ( bc.getClient () );
// {
// browser: { name: "Chrome", version: "83.0.4103.106", major: "83" }
// cpu: { architecture: undefined }
// device: { vendor: undefined, model: undefined, type: undefined }
// engine: { name: "Blink", version: "83.0.4103.106" }
// os: {name: "Mac OS", version: "10.13.6"}
// }List all available audio and video devices.
Return an InputDeviceInfo Array.
bc.getMediaSources ( devices => { console.log ( devices )) } );
// [ {deviceId: "default", groupId: "81bc13...84f48", kind: "audioinput", label: "Internal Microphone"}, { ... } ]arguments
- callback:
Function, function to call when devices list is available
Trigger callback when the list of available audio/video devices has changed
bc.onMediaSourcesUpdated ( () => {
bc.getMediaSources ( devices => { console.log ( devices ) ) }
} ) );
// [ {deviceId: "default", groupId: "81bc13...84f48", kind: "audioinput", label: "Internal Microphone"}, { ... } ]Get a new audio/video stream.
bc.startStream ( {
audio: true,
video: {
width: { min: 1024, ideal: 1280, max: 1920 },
height: { min: 576, ideal: 720, max: 1080 }
}
}, newStream => console.log ( newStream ), error => console.log ( error ) );
bc.startStream ( "screen-sharing:application:12", newStream => console.log ( newStream ) );
// MediaStream { ... }
// MediaStream { ... }In order to be allowed to request a stream your page must be loaded over HTTPS
arguments
- constraints:
Object, request a new audio/video stream, see details here,String, request a new screen-sharing stream, "screen-sharing[:framerate]"
- success:
Function, function called when the stream is available - error:
Function, function called when an error occurred- NotFoundError: requested audio/video device not found
- NotReadableError: requested audio/video not available or is used by another software
- OverconstrainedError: requested constraints cannot be fulfilled
- NotAllowedError: user refused to grant access to requested device
Update stream with new constraints.
bc.updateStream ( localStream, {
video: {
frameRate: { min: 5, ideal: 10, max: 15 }
}
}, updatedStream => console.log ( updatedStream ), error => console.log ( error ) );
// MediaStream { ... }arguments
- stream:
MediaStream, stream to stop - constraints:
Object, see details here - success:
Function, function called when the stream is updated - error:
Function, function called when an error occurred- NotFoundError: requested audio/video device not found
- NotReadableError: requested audio/video not available or is used by another software
- OverconstrainedError: requested constraints cannot be fulfilled
- NotAllowedError: user refused to grant access to requested device
Stop specified stream.
bc.stopStream ( stream, stoppedStream => console.log ( stoppedStream ) );
// MediaStream { ... }arguments
- stream:
MediaStream, stream to stop - callback:
Function, function to call when the stream is stopped
Attach stream to the DOM to render it.
bc.attachStream ( stream, document.body, { mirror: true } );arguments
- stream:
MediaStream, stream to render - node:
DOM node, could be a video/audio player or a container - options
- mirror:
Boolean, flip video vertically, like in a mirror (default:false) - controls:
Boolean, display audio/video controls (default:false) - fullscreen:
Boolean, toggle fullscreen when clicking on the video (default:false)
- mirror:
Refresh stream rendering after it had been updated.
bc.reattachStream ( stream, { mirror: true } );arguments
- stream:
MediaStream, stream to render - options
- mirror:
Boolean, flip video vertically, like in a mirror (default:false) - controls:
Boolean, display audio/video controls (default:false) - fullscreen:
Boolean, toggle fullscreen when clicking on the video (default:false)
- mirror:
Destroy stream rendering.
bc.detachStream ( stream );arguments
- stream:
MediaStream, stream which rendering will be destoyed
Clone a stream.
Return a new MediaStream object.
var newStream = bc.cloneStream ( localStream );arguments
- stream:
MediaStream, stream to clone
Override all audio/video tracks of the targeted stream with the tracks of the specified stream.
Return the target stream.
bc.mergeStream ( newStream, localStream );arguments
- stream:
MediaStream, stream that will be used as source - target:
MediaStream, stream that will be overriden - stop:
Boolean, if true, overriden tracks will be stopped (default: false)
Create a stream with no audio/video tracks.
var emptyStream = bc.dummyStream ();Set a description for audio or video track of the specified stream. The description will be available on the remote side.
bc.setTrackDescription ( localStream, "video", "Front Camera" );
console.log ( localStream.videoDesc )
// Front Cameraarguments
- stream:
MediaStream, targeted stream - kind:
String, type of track:audioorvideo - description:
String, track description
Stop audio or video track for a given stream.
bc.stopTrack ( localStream, "video" );
// Front Cameraarguments
- stream:
MediaStream, targeted stream - kind:
String, type of track:audioorvideo - remove:
Boolean, if true, track is removed from stream after being stopped (default:false)
Join a conference room. The max number of participants can be limited by setting capacity option when first user join the room. If the room doesn’t exist, it will be created.
bc.joinRoom ( "myConferenceRoom", 4 );arguments
- name:
String, room name - capacity:
Number, max participants
events
Event joinedRoom is triggered when user has successfully joined the room, other members already present into the room will receive an event peerJoinedRoom. Event joinRoomError is triggered otherwise
Quit conference room.
bc.quitRoom ( "myConferenceRoom" );arguments
- name:
String, room name
events
Event quittedRoom is triggered when the user has leaved the room, other room members will receive event peerQuittedRoom. Otherwise an event quitRoomError is triggered.
Start a call with a remote user.
bc.call ( "user-1", "myConferenceRoom", { stream: [
localStream,
otherStream
] } );Note: multiple streams can be set at the same time. Eg: person + screen-sharing
arguments
- userid :
String, remote user id - room:
String, room name - option:
- stream:
MediaStreamorMediaStream Array, stream(s) to use for the call - sendonly:
Boolean, whentrueno stream is expected to be sent back (default:false) - audio-codec:
String, set prefered audio codec (opus/48000/2, multiops/48000/5, ...) - audio-codec:
String, set prefered video codec (VP8, VP9, H264, ...) - audio-bitrate:
Number, set max audio bitrate sent/recv (kbp/s) - video-bitrate:
Number, set max video bitrate sent/recv (kbp/s)
- stream:
events
- If the caller hasn’t joined the room previously, he will be automatically added to the room and event
joinedRoomwill be triggered. - If the callee is already present in the room: the call is processed and event
streamAddedis triggered shortly after on both sides when the remote audio/video stream is received. - If the callee is not present in the room: event
incomingRequestis triggered on the remote user side to invite him to join the call. - If the call fails an event
callFailedis triggered on both caller and callee sides.
Update an existing call.
bc.updateCall ( "user-1", "myConferenceRoom", { stream: [
{ update: localStream },
{ add: newStream }
] } );Note: multiple streams can be modified at the same time
- userid :
String, remote user id - room:
String, room name - option:
- stream:
ObjectorObject array, actions to operate on streams- update:
MediaStream, update the actual media{ stream: { update: localStream } } - add:
MediaStream, add a new media to the call{ stream: { add: localStream } } - remove:
MediaStream, remove media from the call{ stream: { remove: localStream } } - copy:
MediaStream Array, copy tracks from media A to media B and update the call{ stream: { copy: [ newStream, localStream ] } }
- update:
- audio-bitrate:
Number, set max audio bitrate sent/recv (kbp/s) - video-bitrate:
Number, set max video bitrate sent/recv (kbp/s)
- stream:
End a call with a user.
bc.endCall ( "user-1", "myConferenceRoom" );arguments
- userid :
String, remote user id - room:
String, room name
events
Event streamClosed is triggered on both sides.
End call with all the users in a room.
bc.endCalls ("myConferenceRoom" );arguments
- room:
String, room name
events
Event streamClosed is triggered on the both sides for each call.
Create a new data channel with a remote participant.
bc.openDataChannel ( "user-1", "chat", "myConferenceRoom" );arguments
- userid :
String, remote user id - label:
String, data channel label - room:
String, room name
events
- If the caller hasn’t joined the room previously, he will be automatically added to the room and event
joinedRoomwill be triggered, then the eventdataChannelCreatedis triggered. - If the callee is already present in the room: the request is processed and the event
dataChannelRequestedis triggered. - If the callee is not present in the room: event
incomingRequestis triggered on the remote user side to invite him to accept the request. - If the request fails an event
callFailedis triggered on both caller and callee sides.
Send a file to remote participant(s).
bc.sendFile ( "user-1", "myConferenceRoom", "file://..." );arguments
- userid :
String, remote user id - room:
String, room name - path:
String, file path
events
- If the sender hasn’t joined the room previously, he will be automatically added to the room and event
joinedRoomwill be triggered - when a new file transfert is initiated event
fileTransferWaitingis triggered on sender side, while eventnewFileTransferis triggered on recipient side - if file transfert has been declined by recipient, event
fileTransferAbortedis triggered on both sides - once recipient has accepted file transfert, event
fileTransferProgressis triggered on both sides periodically to update transfert progression and eventfileTransferBitrateis triggered periodically to update transfert bitrate - once file transfert is completed, event
fileSentis triggered on sender side and eventfileReceivedis triggered on reciever side
Send a customized signal to a conference participant.
bc.sendCustomSignal ( "user-1", "myConferenceRoom", { action: "wizz" } );arguments
- userid :
String, remote user id - room:
String, room name - data:
StringorObject, request payload
events
- event
onCustomSignalis triggered on the remote participant side
return a MediaStream Array for local streams.
console.log ( bc.getLocalStreams () );
// [ `MediaStream`, `MediaStream`, ... ]return an Object containing pairs of remote userid / MediaStream.
console.log ( bc.getRemoteStreams ( "myConferenceRoom" ) );
// { "St9d9JU7": `MediaStream`, ... }arguments
- room:
String, room name
return an Object containing pairs of remote userid / Array of sent MediaStreamTrack.
console.log ( bc.getLocalTracks () );
// { "St9d9JU7": [ `MediaStreamTrack`, MediaStreamTrack ] }return an Object containing pairs of remote userid / Array of received MediaStreamTrack.
console.log ( bc.getRemoteTracks ( "myConferenceRoom" ) );
// { "St9d9JU7": [ `MediaStreamTrack`, MediaStreamTrack ] }arguments
- room:
String, room name
Return an Object containing pairs of remote userid / DataChannel.
console.log ( bc.getDataChannels ( "myConferenceRoom" ) );
// { "St9d9JU7": `DataChannel`, ... }arguments
- room:
String, room name
Return an Object containing pairs of remote userid / FileTransfert.
console.log ( bc.getFileTransferts ( "myConferenceRoom" ) );
// { "St9d9JU7": `FileTransfert`, ... }arguments
- room:
String, room name
Return an Array containing room members.
console.log ( bc.getRoomMembers ( "myConferenceRoom" ) );
// [ { "id": "St9d9JU7", name:"Jane Smith" }, ... ]arguments
- room:
String, room name
Request remote user presence status.
bc.getPresence ( 'rfpWEk' );arguments
- userid :
String, remote user id
events
- Event
presenceis triggered when the presence status is received.
Set local user presence status.
bc.setPresence ( 'online' );arguments
- status :
String, presence status: online, away, busy, offline (default: online)
Allow Bistri Conference to access to audiocontext. Must be called on a user gesture.
Necessary to use
monitorAudioActivitymethod
document.addEventListener ( "click", bc.allowMonitorAudioActivity );Monitor audio ouput level for a given MediaStream.
Level is expressed in percent (0-100%)
bc.monitorAudioActivity ( localStream, level => console.log ( level ) )
// 56
// 20
// 25arguments
- stream:
MediaStream, stream to monitor - callback:
Function, function to call each time there is a level change
Mute audio ouput for a given stream.
bc.muteSound ( localStream, true );arguments
- stream:
MediaStream, stream to mute - mute:
Boolean, mute status
Get audio ouput status for a given stream.
Return a Boolean.
console.log ( bc.isSoundMuted ( localStream ) );
// truearguments
- stream:
MediaStream, checked stream
Mute audio ouput for every incoming streams.
bc.muteAllSounds ( true );arguments
- mute:
Boolean, mute status
Get audio ouput status.
Return a Boolean.
console.log ( bc.isAllSoundsMuted ( localStream ) );
// trueMute video input for a given stream.
bc.muteVideo ( localStream, true );arguments
- stream:
MediaStream, stream to mute - mute:
Boolean, mute status
events
- Event
streamMuteChangeis triggered on the remote side.
Instead of muting video track this method add/remove video track from current calls.
Return a Boolean reflecting the current video input status.
bc.toggleVideo ( localStream );arguments
- stream:
MediaStream, stream to toggle
events
- Event
streamMuteChangeis triggered on the remote side.
Get video input status.
Return a Boolean.
console.log ( bc.isVideoMuted () );
// trueMute audio input.
bc.muteMicrophone ( true );
// truearguments
- mute:
Boolean, mute status
Get audio input status.
Return a Boolean.
console.log ( bc.isMicrophoneMuted () );
// trueBind signaling events.
Return a reference associated to the handler.
const handler_ref = bc.signaling.bind ( event, data => {} );Unbind can be done using handler reference (remove a specific handler) or by an event name (remove all handlers)
bc.signaling.unbind ( handler_ref );
// or
bc.signaling.unbind ( event );-
error: triggered when a global error occurred.
-
arguments:
- error
Object
{ "code": "xxx", // error code "text": "..." // error reason }
- error
-
-
connected: triggered when client is connected to the signaling server.
-
event related to:
connect() -
arguments:
- session
Object
{ "id": "rfpWEk" // user session id }
- session
-
-
disconnected: triggered when client is gracefully disconnected.
- event related to:
disconnect()
- event related to:
-
connectionResumed: triggered when client reconnect after a disconnection.
-
connectionError: triggered when connection to signaling server is lost.
-
arguments:
- error
Object
{ "code": "xxx", // error code "reason": "..." // error reason }
- error
-
-
joinedRoom: triggered when room has been joined
-
event related to:
joinRoom() -
arguments:
- data
Object
{ "room": "aUpS45g7J0w", // room name "members":[ // array of users already present in the room { "id": "aVlxUi", // remote peer id "name": "Jane Doe" // remote user display name }, ], }
- data
-
-
joinRoomError: triggered when an error occurred while joining room
-
event related to:
joinRoom() -
arguments:
- error
Object
{ "code": "xxx", // error code "reason": "..." // error reason }
- error
-
-
quittedRoom: triggered when room has been left
-
event related to:
quitRoom() -
arguments:
- room
Object
{ "room": "aUpS45g7J0w" // room name }
- room
-
-
quitRoomError: triggered when an error occurred while quitting room
-
event related to:
quitRoom() -
arguments:
- error
Object
{ "code": "xxx", // error code "reason": "..." // error reason }
- error
-
-
peerJoinedRoom: triggered when a new participant join the room
-
arguments:
- peer
Object
{ "room": "aUpS45g7J0w", // room name "name": "John Doe", // remote peer name "pid": "rfpWEk" // remote peer id }
- peer
-
-
peerQuittedRoom: triggered when a new participant leave the room
-
arguments:
- peer
Object
{ "room": "aUpS45g7J0w", // room name "pid": "rfpWEk" // remote peer id }
- peer
-
-
customSignal: triggered when a custom signal is received
- event related to:
sendCustomSignal() - arguments:
- data
Object
- data
- event related to:
-
incomingRequest: triggered when a remote user invite you to join a room
-
event related to:
call(),openDataChannel() -
arguments:
- request
Object
{ "room": "aUpS45g7J0w", // room name "pid": "rfpWEk", // remote peer id "event": "call" // request type "call" or "datachannel" }
- request
-
-
incomingCall: triggered if a new call or data channel request is received and
autoAcceptCalloption has been set tofalse-
event related to:
call(),openDataChannel() -
arguments:
- call
Object
{ "type": "media", // call type (media, datachannel) "pid": "rfpWEk", // remote peer id "room": "aUpS45g7J0w", // room name "options": {…}, // call options "client": {…}, // resquester's browser info "sendonly": false, // bidirectional call info "accept": function (){…}, // function to accept call "reject": function (){…} // function to reject call }
- call
-
-
callRejected: triggered when a user reject an incoming call/data channel request
- event related to:
call.reject() - arguments:
- pid
String: peer id - room
String: room name
- pid
- event related to:
-
callFailed: triggered when a connection failed to be established between 2 participants
-
event related to:
call(),openDataChannel(), sendFile() -
arguments:
- room
String: room name - pid
String: remote peer id - message
String: error message - trace
Array: peerConnection log - client
Object: remote browser info
{ "name": "chrome", // browser name "version": "83", // browser version "vendor": "google inc.", // browser vendor "os": "macos", // os "osversion": "10.13.6" // os version }
- room
-
-
callEnded: triggered when a call or a datachannel ends
- event related to:
endCall(),endCalls() - arguments:
- pid
String: remote peer id - room
String: room name
- pid
- event related to:
-
presence: triggered when a presence status is received
-
event related to:
getPresence() -
arguments:
- presence
Object: remote peer id
{ "id": "rfpWEk", // peer id "presence": "online" // presence status }
- presence
-
Bind streams events.
Return a reference associated to the handler.
const handler_ref = bc.streams.bind ( event, data => {} );Unbind can be done using handler reference (remove a specific handler) or by an event name (remove all handlers)
bc.streams.unbind ( handler_ref );
// or
bc.streams.unbind ( event );-
streamMuteChange: triggered when video mute status change
- event related to:
muteVideo() - arguments:
- status
String: mute status - pid
String: remote peer id
- status
- event related to:
-
streamAdded: triggered when a new stream is available
- event related to:
call(),updateCall() - arguments:
- stream
MediaStream: remote stream - pid
String: remote peer id
- stream
- event related to:
-
streamUpdated: triggered when a stream has been updated
- event related to:
call(),updateCall() - arguments:
- stream
MediaStream: remote stream - pid
String: remote peer id
- stream
- event related to:
-
streamClosed: triggered when a stream has been closed
- event related to:
endCall(),endCalls() - arguments:
- stream
MediaStream: remote stream - pid
String: remote peer id
- stream
- event related to:
-
trackAdded: triggered when a new stream track has been added
- event related to:
call(),updateCall() - arguments:
- track
MediaStreamTrack: new remote audio/video track - stream
MediaStream: remote stream - pid
String: remote peer id
- track
- event related to:
-
trackRemoved: triggered when a stream track has been removed
- event related to:
call(),updateCall() - arguments:
- track
MediaStreamTrack: remote audio/video track removed - stream
MediaStream: remote stream - pid
String: remote peer id
- track
- event related to:
-
streamStatsUpdated: triggered when connection statistics have been updated
-
arguments:
- stats
Object:
{ "send": {…}, // sent data stats "recv": {…}, // received data stats "transport": {…}, // transport info "candidates": {…}, // ICE candidates info "client": {…} // remote browser info "cpuPressure": "…" // cpu stress level (nominal, fair, serious, critical) }
- pid
String: remote peer id - room
String: room name
- stats
-
-
devicesUpdated: triggered when input/output devices list has been updated
- arguments:
- track
MediaStreamTrack: remote audio/video track removed - stream
MediaStream: remote stream - pid
String: remote peer id
- track
- arguments:
Bind data channel events.
Return a reference associated to the handler.
const handler_ref = bc.channels.bind ( event, data => {} );Unbind can be done using handler reference (remove a specific handler) or by an event name (remove all handlers)
bc.channels.unbind ( handler_ref );
// or
bc.channels.unbind ( event );- dataChannelCreated: triggered when a new data channel has been created on the caller side
-
event related to:
openDataChannel() -
arguments:
- channel
DataChannel: data channel object
{ "label": "chat", // data channel label "send": function ( message ) {…}, // send message "close": function () {…}, // close data channel "onOpen": undefined, // "on open" callback "onMessage": undefined, // "on new message" callback "onClose": undefined, // "on close" callback }
- pid
String: remote peer id
- channel
-
- dataChannelRequested: triggered when a new data channel has been requested on the callee side
-
event related to:
openDataChannel() -
arguments:
- channel
DataChannel: data channel object
{ "label": "chat", // data channel label "send": function ( message ) {…}, // send message "close": function () {…}, // close data channel "onOpen": undefined, // "on open" callback "onMessage": undefined, // "on new message" callback "onClose": undefined, // "on close" callback }
- pid
String: remote peer id
- channel
-
Bind file transfert events.
Return a reference associated to the handler.
const handler_ref = bc.files.bind ( event, data => {} );Unbind can be done using handler reference (remove a specific handler) or by an event name (remove all handlers)
bc.files.unbind ( handler_ref );
// or
bc.files.unbind ( event );-
fileTransferWaiting: triggered when a file transfert is created on the sender side
-
event related to:
sendFile() -
arguments:
- channel
DataChannel: data channel object - pid
String: recipient id - file
Object: file info
{ "id": "iu798d4n", // file transfert id "name": "my_file.pdf", // file name "size": "55.05 KB" // file size }
- channel
-
-
newFileTransfer: triggered when a file transfert request is received on the recipient side
-
event related to:
sendFile() -
arguments:
- channel
DataChannel: data channel object - pid
String: sender id - file
Object: file info
{ "id": "iu798d4n", // file transfert id "name": "my_file.pdf", // file name "size": "55.05 KB" // file size }
- answer
Object: answer to file transfert request
{ "ok": function () {…}, // accept file transfert request "cancel": function () {…} // reject file transfert request }
- channel
-
-
fileTransferProgress: triggered periodically while the file transfert is in progress
- event related to:
answer.ok() - arguments:
- id:
String, file transfert uid - progression:
Number, file transfert progression in %
- id:
- event related to:
-
fileTransferBitrate: triggered periodically while the file transfert is in progress
- event related to:
answer.ok() - arguments:
- id:
String, file transfert uid - progression:
String, file transfert progression in %
- id:
- event related to:
-
fileTransferAborted: triggered when file transfert resquest has been rejected by the recipient
- event related to:
answer.cancel() - arguments:
- id:
String, file transfert uid
- id:
- event related to:
-
fileSent: triggered when the file transfert is completed on the sender side
- arguments:
- id:
String, file transfert uid
- id:
- arguments:
-
fileReceived: triggered when the file transfert is completed on the recipient side
-
arguments:
- id:
String, file transfert uid - file
Object: file info
{ id: "iu798d4n", // file transfert id name: "my_file.pdf", // file name url: "…" // file download url }
- id:
-




