webauto-media-client
/
1.8.0
webauto-media-client 1.8.0
Install from the command line:
Learn more about npm packages
$ npm install @tier4/webauto-media-client@1.8.0
Install via package.json:
"@tier4/webauto-media-client": "1.8.0"
About this version
A JS client library for Web.Auto Media APIs
- JavaScript/TypeScript (ES2018)
- Google Chrome 84 and higher
ReomteDevices
provides an I/F to access the devices (cameras and microphones) installed on a vehicle.
- You can query devices on a specific vehicle by
getRemoteDevices(vehicleId, projectId, environmentId)
. You now gotRemoteDevices
, a catalog of cameras and microphones on the vehicle. -
RemoteDevices.cameras
is a list ofRemoteCamera
s andRemoteDevices.microphones
containsRemoteMicrophone
s. Both ofRemoteCamera
andRemoteMicrophone
are derived fromRemoteDevice
. -
RemoteDevice
provides two properties for identification:id
is the unique ID associated with the specific device andtag
string gives you a hint where and what-for the device is installed. -
RemoteDevice
also providesconnect()
method. You can get a media stream by calling this asynchronous method.
import { MediaClient } from '@tier4/webauto-media-client';
// You have to set authtoken callback to get fresh authtoken (it will be invoked occasionally)
MediaClient.addAuthTokenCallback(async () => {
return await fetchAccessTokenUsingWebAutoAuthApi();
});
// Then, query `MediaClient.RemoteDevices`
const devices = await MediaClient.getRemoteDevices({
vehicleId,
projectId,
environmentId,
});
// For playback, you would need HTMLVideoElement instances
const videos = prepareVideoElements(devices.cameras.length);
devices.cameras.forEach(async (camera, i) => {
// You can distinguish each devices with `id` and `tag`
showCameraIdAndLocation(camera.id, camera.tag);
// You can get a MediaStream from the camera device
await camera.connect((stream) => {
// this callback is invoked everytime new stream is ready
// (note: publishers could stop and restart publishing arbitrary times)
// to start playback, you first set `stream` to video's `srcObject` property
videos[i].srcObject = stream;
// ...then, kick `play()` method
await videos[i].play();
});
});
// Like wise, you can play audio from microphones.
devices.microphones.forEach(async (microphone) => {
const audio = new Audio();
audio.srcObject = await microphone.connect();
await audio.play();
});
RemoteCall
provides telephone-like API between operators and passengers.
import { MediaClient } from '@tier4/webauto-media-client';
async function setup() {
await updateStatus('ready');
// You have to set authtoken callback to get fresh authtoken
MediaClient.addAuthTokenCallback(async () => {
return await fetchAccessTokenUsingWebAutoAuthApi();
});
// Then, create `MediaClient.RemoteCall` instance
const call = MediaClient.createRemoteCall(
{
projectId,
vehicleId,
environmentId,
role: 'passenger', // 'passenger' or 'operator'
},
// See `onRinging` below to understand how to handle incoming call
onRinging
);
return call;
}
async function makeCall(call: MediaClient.RemoteCall) {
// You can initiate call session by passing target and stream
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false,
});
const calling = call.call('operator', stream);
await updateStatus('calling');
// Wait for answer from the peer or cancel by users' operation
const talking = await Promise.race([
async () => {
try {
return await calling.waitForAnswer();
} catch (error) {
if (error instanceof MediaClient.RemoteCall.Canceled) {
// Thrown when you call `calling.cancel()`
console.info('The call is canceled by the caller');
} else if (error instanceof MediaClient.RemoteCall.Refused) {
// Thrown when the other party refuses by calling `ringing.refuse()`
showPopupTheOtherPartyRefusedTheCall();
} else {
// We do not throw other errors, but it is recommended to check this case
console.log('Unexpected error', error);
}
return null;
}
},
async () => {
await waitForUserClickCancelButton();
await calling.cancel(); // see the catch clause above
return null;
},
]);
// To cancel ongoing call, call `cancel()` method
if (!talking) {
await calling.cancel();
await updateStatus('ready');
return;
}
await onTalking(talking);
// Now you can make another call session
await updateStatus('ready');
}
// This callback function will be invoked on every new incoming session
async function onRinging(ringing: MediaClient.Ringing) {
await updateStatus('ringing');
await waitForUserClickAnswerButton();
// Answer the call by passing stream and get `MediaClient.Converstaion` object
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false,
});
const talking = await ringing.answer(stream);
await onTalking(talking);
// Now you can wait for another call session
await updateStatus('ready');
}
async function onTalking(talking: MediaClient.Conversation) {
// Start playing incoming voice
const audio = new Audio();
audio.srcObject = talking.stream;
await audio.play();
await updateStatus('talking');
// Wait for hangup by peer or by user
await Promise.race([
// When the user click 'hangup' button, call `hanguUp()` to close the call
waitForUserClickHangupButton().then(() => talking.hangUp()),
// or wait for hangup by the other party
talking.waitForHangUp(),
]);
}