@skyway-sdk/core
Version:
The official Next Generation JavaScript SDK for SkyWay
260 lines • 11.5 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MediaDevice = exports.SkyWayStreamFactory = exports.StreamFactory = void 0;
const common_1 = require("@skyway-sdk/common");
const errors_1 = require("../errors");
const util_1 = require("../util");
const audio_1 = require("./stream/local/audio");
const customVideo_1 = require("./stream/local/customVideo");
const data_1 = require("./stream/local/data");
const video_1 = require("./stream/local/video");
const log = new common_1.Logger('packages/core/src/media/factory.ts');
class StreamFactory {
/**@private */
constructor() {
/**
* @description [japanese] 一度参照した種類のデバイスの状態が変化した時に発火するイベント
*/
this.onDeviceChange = new common_1.Event();
this._devices = [];
if (!(navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices)) {
throw (0, util_1.createError)({
operationName: 'StreamFactory.constructor',
info: errors_1.errors.mediaDevicesNotFound,
path: log.prefix,
});
}
navigator.mediaDevices.addEventListener('devicechange', () => __awaiter(this, void 0, void 0, function* () {
const devices = yield this._enumerateDevicesArray();
const removed = [];
this._devices.forEach((prev) => {
if (!devices.map((d) => d.id).includes(prev.id)) {
removed.push(prev);
}
});
const added = [];
devices
.map((d) => d.id)
.forEach((next) => {
if (!this._devices.map((d) => d.id).includes(next)) {
added.push(devices.find((d) => d.id === next));
}
});
log.debug('device changed', { added, removed });
removed.forEach((device) => {
this.onDeviceChange.emit({ state: 'removed', device });
});
added.forEach((device) => {
this.onDeviceChange.emit({ state: 'added', device });
});
this._devices = devices;
}));
}
_enumerateDevicesArray() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield navigator.mediaDevices.enumerateDevices();
return devices
.map((d) => new MediaDevice(d))
.filter((d) => d.id.length > 0);
});
}
_enumerateDevicesWithAuth({ video, audio } = {
audio: true,
video: true,
}) {
return __awaiter(this, void 0, void 0, function* () {
let tracks = [];
if (video || audio) {
const stream = yield navigator.mediaDevices.getUserMedia({
video,
audio,
});
tracks = stream.getTracks();
}
this._devices = yield this._enumerateDevicesArray();
tracks.forEach((t) => {
t.stop();
});
return this._devices;
});
}
/**
* @description [japanese] デバイスの一覧を取得する
*/
enumerateDevices() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield this._enumerateDevicesWithAuth();
return devices;
});
}
/**
* @description [japanese] 映像入力デバイスの一覧を取得する
*/
enumerateInputVideoDevices() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield this._enumerateDevicesWithAuth({ video: true });
return devices.filter((d) => d.kind === 'videoinput');
});
}
/**
* @description [japanese] 音声入力デバイスの一覧を取得する
*/
enumerateInputAudioDevices() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield this._enumerateDevicesWithAuth({ audio: true });
return devices.filter((d) => d.kind === 'audioinput');
});
}
/**
* @description [japanese] 音声出力デバイスの一覧を取得する
*/
enumerateOutputAudioDevices() {
return __awaiter(this, void 0, void 0, function* () {
const devices = yield this._enumerateDevicesWithAuth({ audio: true });
return devices.filter((d) => d.kind === 'audiooutput');
});
}
/**
* @description [japanese] CameraのVideoStreamを作成する
*/
createCameraVideoStream(options = {}) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
options.stopTrackWhenDisabled = (_a = options.stopTrackWhenDisabled) !== null && _a !== void 0 ? _a : true;
const [track] = (yield navigator.mediaDevices.getUserMedia({ video: options })).getTracks();
const stream = new video_1.LocalVideoStream(track, options);
stream._setLabel('camera');
return stream;
});
}
/**
* @description [japanese] マイクのAudioStreamを作成する
*/
createMicrophoneAudioStream(options = {}) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
options.stopTrackWhenDisabled = (_a = options.stopTrackWhenDisabled) !== null && _a !== void 0 ? _a : true;
const [track] = (yield navigator.mediaDevices.getUserMedia({ audio: options })).getTracks();
const stream = new audio_1.LocalAudioStream(track, options);
stream._setLabel('microphone');
return stream;
});
}
/**
* @description [japanese]
* PCブラウザでのみ利用可能なAPI。
* VideoStreamは常に取得される(AudioStreamのみ取得することはできない)
* audioオプションを有効にするとAudioStreamを取得することができる。
* audioオプションはWindowsのChromeにしか対応しておらず、
* それ以外の環境では有効にしても戻り値のaudioにはundefinedが返される。
*/
createDisplayStreams(options = {}) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
const videoOption = (_a = options.video) !== null && _a !== void 0 ? _a : {};
(_b = videoOption.stopTrackWhenDisabled) !== null && _b !== void 0 ? _b : (videoOption.stopTrackWhenDisabled = true);
let audioOption = options.audio;
if (audioOption) {
audioOption = typeof audioOption === 'boolean' ? {} : audioOption;
(_c = audioOption.stopTrackWhenDisabled) !== null && _c !== void 0 ? _c : (audioOption.stopTrackWhenDisabled = true);
}
options = { audio: audioOption, video: videoOption };
const stream = yield navigator.mediaDevices.getDisplayMedia(options);
const [video] = stream.getVideoTracks();
const [audio] = stream.getAudioTracks();
if (options.audio && !audio) {
log.warn((0, util_1.createWarnPayload)({
operationName: 'StreamFactory.createDisplayStreams',
detail: 'This client does not support device audio capture',
}));
}
const videoStream = new video_1.LocalVideoStream(video, Object.assign(Object.assign({}, videoOption), { isDisplayMedia: true }));
videoStream._setLabel('displayVideo');
const audioStream = audio
? new audio_1.LocalAudioStream(audio, Object.assign(Object.assign({}, audioOption), { isDisplayMedia: true }))
: undefined;
if (audioStream) {
audioStream._setLabel('displayAudio');
}
return {
video: videoStream,
audio: audioStream,
};
});
}
/**
* @description [japanese] DataStreamを作成する
*/
createDataStream(options = {}) {
return __awaiter(this, void 0, void 0, function* () {
return new data_1.LocalDataStream(options);
});
}
/**
* @description [japanese] CameraのVideoStreamとマイクのAudioStreamを作成する
*/
createMicrophoneAudioAndCameraStream({ audio, video, } = {}) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const stream = yield navigator.mediaDevices.getUserMedia({
audio: audio !== null && audio !== void 0 ? audio : true,
video: video !== null && video !== void 0 ? video : true,
});
const [audioTrack] = stream.getAudioTracks();
const [videoTrack] = stream.getVideoTracks();
audio = audio !== null && audio !== void 0 ? audio : {};
audio.stopTrackWhenDisabled = (_a = audio.stopTrackWhenDisabled) !== null && _a !== void 0 ? _a : true;
const audioStream = new audio_1.LocalAudioStream(audioTrack, audio);
audioStream._setLabel('microphone');
video = video !== null && video !== void 0 ? video : {};
video.stopTrackWhenDisabled = (_b = video.stopTrackWhenDisabled) !== null && _b !== void 0 ? _b : true;
const videoStream = new video_1.LocalVideoStream(videoTrack, video);
videoStream._setLabel('camera');
return {
audio: audioStream,
video: videoStream,
};
});
}
/**
* @description [japanese] CustomVideoStreamを作成する
*/
createCustomVideoStream(processor, options = {}) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
options.stopTrackWhenDisabled = (_a = options.stopTrackWhenDisabled) !== null && _a !== void 0 ? _a : true;
const stream = new customVideo_1.LocalCustomVideoStream(options);
const processedStream = yield processor.createProcessedStream({
constraints: (_b = options.constraints) !== null && _b !== void 0 ? _b : {},
stopTrackWhenDisabled: options.stopTrackWhenDisabled,
onUpdateTrack: (track) => {
return stream.updateTrack(track);
},
});
yield stream.setStream(processedStream);
return stream;
});
}
}
exports.StreamFactory = StreamFactory;
exports.SkyWayStreamFactory = new StreamFactory();
/**@internal */
class MediaDevice {
/**@private */
constructor(info) {
this.id = info.deviceId;
this.label = info.label;
this.kind = info.kind;
}
}
exports.MediaDevice = MediaDevice;
//# sourceMappingURL=factory.js.map