@whereby.com/core 1.2.9 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +180 -6
- package/dist/index.d.cts +26 -0
- package/dist/index.d.mts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.mjs +181 -7
- package/dist/legacy-esm.js +181 -7
- package/dist/redux/index.cjs +161 -7
- package/dist/redux/index.d.cts +154 -1
- package/dist/redux/index.d.mts +154 -1
- package/dist/redux/index.d.ts +154 -1
- package/dist/redux/index.js +160 -8
- package/dist/redux/index.mjs +160 -8
- package/package.json +11 -3
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import nodeBtoa from 'btoa';
|
|
2
|
-
import { assert, fromLocation, ServerSocket, getDeviceData, getStream, getUpdatedDevices, RtcManagerDispatcher, setClientProvider, subscribeIssues } from '@whereby.com/media';
|
|
2
|
+
import { assert, fromLocation, ServerSocket, getDeviceData, getStream, getUpdatedDevices, replaceTracksInStream, RtcManagerDispatcher, setClientProvider, subscribeIssues } from '@whereby.com/media';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
5
5
|
import { createListenerMiddleware, createSlice, createAction, createSelector, createAsyncThunk, isAnyOf, combineReducers, configureStore, addListener } from '@reduxjs/toolkit';
|
|
@@ -1145,9 +1145,9 @@ const createReactor = (selectors, callback) => {
|
|
|
1145
1145
|
});
|
|
1146
1146
|
};
|
|
1147
1147
|
|
|
1148
|
-
const coreVersion = "1.
|
|
1148
|
+
const coreVersion = "1.3.1";
|
|
1149
1149
|
|
|
1150
|
-
const initialState = {
|
|
1150
|
+
const initialState$1 = {
|
|
1151
1151
|
isNodeSdk: false,
|
|
1152
1152
|
isActive: false,
|
|
1153
1153
|
isDialIn: false,
|
|
@@ -1161,7 +1161,7 @@ const initialState = {
|
|
|
1161
1161
|
};
|
|
1162
1162
|
const appSlice = createSlice({
|
|
1163
1163
|
name: "app",
|
|
1164
|
-
initialState,
|
|
1164
|
+
initialState: initialState$1,
|
|
1165
1165
|
reducers: {
|
|
1166
1166
|
doAppStart: (state, action) => {
|
|
1167
1167
|
const url = new URL(action.payload.roomUrl);
|
|
@@ -1688,6 +1688,12 @@ const localMediaSlice = createSlice({
|
|
|
1688
1688
|
builder.addCase(doSwitchLocalStream.rejected, (state) => {
|
|
1689
1689
|
return Object.assign(Object.assign({}, state), { isSwitchingStream: false });
|
|
1690
1690
|
});
|
|
1691
|
+
builder.addCase(doLocalStreamEffect.fulfilled, (state, { payload }) => {
|
|
1692
|
+
if (!payload) {
|
|
1693
|
+
return state;
|
|
1694
|
+
}
|
|
1695
|
+
return Object.assign(Object.assign({}, state), { beforeEffectTracks: Object.assign(Object.assign({}, state.beforeEffectTracks), payload.beforeEffectTracks) });
|
|
1696
|
+
});
|
|
1691
1697
|
},
|
|
1692
1698
|
});
|
|
1693
1699
|
const { deviceBusy, setCurrentCameraDeviceId, setCurrentMicrophoneDeviceId, setCurrentSpeakerDeviceId, toggleCameraEnabled, toggleMicrophoneEnabled, toggleLowDataModeEnabled, setLocalMediaOptions, setLocalMediaStream, localMediaStopped, localStreamMetadataUpdated, } = localMediaSlice.actions;
|
|
@@ -1817,6 +1823,15 @@ const doSwitchLocalStream = createAppAsyncThunk("localMedia/doSwitchLocalStream"
|
|
|
1817
1823
|
if (!replaceStream) {
|
|
1818
1824
|
return;
|
|
1819
1825
|
}
|
|
1826
|
+
const beforeEffectTracks = selectLocalMediaBeforeEffectTracks(state);
|
|
1827
|
+
if (audioId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.audio)) {
|
|
1828
|
+
beforeEffectTracks.audio.stop();
|
|
1829
|
+
beforeEffectTracks.audio = undefined;
|
|
1830
|
+
}
|
|
1831
|
+
if (videoId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.video)) {
|
|
1832
|
+
beforeEffectTracks.video.stop();
|
|
1833
|
+
beforeEffectTracks.video = undefined;
|
|
1834
|
+
}
|
|
1820
1835
|
try {
|
|
1821
1836
|
const { replacedTracks } = yield getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: audioId === undefined ? false : audioId, videoId: videoId === undefined ? false : videoId, type: "exact" }), { replaceStream });
|
|
1822
1837
|
const deviceId = audioId || videoId;
|
|
@@ -1825,7 +1840,7 @@ const doSwitchLocalStream = createAppAsyncThunk("localMedia/doSwitchLocalStream"
|
|
|
1825
1840
|
deviceId,
|
|
1826
1841
|
}));
|
|
1827
1842
|
}
|
|
1828
|
-
return { replacedTracks };
|
|
1843
|
+
return { replacedTracks, beforeEffectTracks };
|
|
1829
1844
|
}
|
|
1830
1845
|
catch (error) {
|
|
1831
1846
|
console.error(error);
|
|
@@ -1876,6 +1891,46 @@ const doStopLocalMedia = createAppThunk(() => (dispatch, getState) => {
|
|
|
1876
1891
|
}
|
|
1877
1892
|
dispatch(localMediaStopped());
|
|
1878
1893
|
});
|
|
1894
|
+
const doLocalStreamEffect = createAppAsyncThunk("localMedia/doLocalStreamEffect", (_a, _b) => __awaiter(void 0, [_a, _b], void 0, function* ({ effectStream, only, stopBeforeTrack, }, { getState }) {
|
|
1895
|
+
var _c;
|
|
1896
|
+
const state = getState();
|
|
1897
|
+
let beforeEffectTracks = selectLocalMediaBeforeEffectTracks(state);
|
|
1898
|
+
const beforeTrack = beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks[only];
|
|
1899
|
+
if (!effectStream && !beforeTrack)
|
|
1900
|
+
return;
|
|
1901
|
+
try {
|
|
1902
|
+
const stream = selectLocalMediaStream(state);
|
|
1903
|
+
let replacedTracks = null;
|
|
1904
|
+
if (!stream) {
|
|
1905
|
+
throw new Error("No local media stream");
|
|
1906
|
+
}
|
|
1907
|
+
if (effectStream) {
|
|
1908
|
+
if (!beforeTrack) {
|
|
1909
|
+
beforeEffectTracks = {
|
|
1910
|
+
[only]: (_c = (only === "audio" ? stream === null || stream === void 0 ? void 0 : stream.getAudioTracks() : stream === null || stream === void 0 ? void 0 : stream.getVideoTracks())) === null || _c === void 0 ? void 0 : _c[0],
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
replacedTracks = replaceTracksInStream(stream, effectStream, only);
|
|
1914
|
+
}
|
|
1915
|
+
else if (!stopBeforeTrack) {
|
|
1916
|
+
replacedTracks = replaceTracksInStream(stream, beforeTrack ? new MediaStream([beforeTrack]) : new MediaStream(), only);
|
|
1917
|
+
beforeEffectTracks = {
|
|
1918
|
+
[only]: undefined,
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
else if (beforeTrack) {
|
|
1922
|
+
beforeEffectTracks = {
|
|
1923
|
+
[only]: undefined,
|
|
1924
|
+
};
|
|
1925
|
+
beforeTrack.stop();
|
|
1926
|
+
}
|
|
1927
|
+
return { effectStream, beforeEffectTracks, replacedTracks };
|
|
1928
|
+
}
|
|
1929
|
+
catch (error) {
|
|
1930
|
+
console.error("Error applying local stream effect", error);
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
}));
|
|
1879
1934
|
const selectBusyDeviceIds = (state) => state.localMedia.busyDeviceIds;
|
|
1880
1935
|
const selectCameraDeviceError = (state) => state.localMedia.cameraDeviceError;
|
|
1881
1936
|
const selectCurrentCameraDeviceId = (state) => state.localMedia.currentCameraDeviceId;
|
|
@@ -1896,6 +1951,7 @@ const selectLocalMediaStream = (state) => state.localMedia.stream;
|
|
|
1896
1951
|
const selectMicrophoneDeviceError = (state) => state.localMedia.microphoneDeviceError;
|
|
1897
1952
|
const selectLocalMediaStartError = (state) => state.localMedia.startError;
|
|
1898
1953
|
const selectLocalMediaIsSwitchingStream = (state) => state.localMedia.isSwitchingStream;
|
|
1954
|
+
const selectLocalMediaBeforeEffectTracks = (state) => state.localMedia.beforeEffectTracks;
|
|
1899
1955
|
const selectLocalMediaConstraintsOptions = createSelector(selectLocalMediaDevices, selectCurrentCameraDeviceId, selectCurrentMicrophoneDeviceId, selectIsLowDataModeEnabled, (devices, videoId, audioId, lowDataMode) => ({
|
|
1900
1956
|
devices,
|
|
1901
1957
|
videoId,
|
|
@@ -1992,7 +2048,7 @@ startAppListening({
|
|
|
1992
2048
|
},
|
|
1993
2049
|
});
|
|
1994
2050
|
startAppListening({
|
|
1995
|
-
matcher: isAnyOf(doStartLocalMedia.fulfilled, doUpdateDeviceList.fulfilled, doSwitchLocalStream.fulfilled, doSwitchLocalStream.rejected),
|
|
2051
|
+
matcher: isAnyOf(doStartLocalMedia.fulfilled, doUpdateDeviceList.fulfilled, doSwitchLocalStream.fulfilled, doSwitchLocalStream.rejected, doLocalStreamEffect.fulfilled),
|
|
1996
2052
|
effect: (_action, { dispatch, getState }) => {
|
|
1997
2053
|
const state = getState();
|
|
1998
2054
|
const stream = selectLocalMediaStream(state);
|
|
@@ -3043,7 +3099,7 @@ startAppListening({
|
|
|
3043
3099
|
},
|
|
3044
3100
|
});
|
|
3045
3101
|
startAppListening({
|
|
3046
|
-
|
|
3102
|
+
matcher: isAnyOf(doSwitchLocalStream.fulfilled, doLocalStreamEffect.fulfilled),
|
|
3047
3103
|
effect: ({ payload }, { getState }) => {
|
|
3048
3104
|
var _a;
|
|
3049
3105
|
const stream = selectLocalMediaStream(getState());
|
|
@@ -4059,11 +4115,107 @@ const doRejectWaitingParticipant = createRoomConnectedThunk((payload) => (dispat
|
|
|
4059
4115
|
});
|
|
4060
4116
|
const selectWaitingParticipants = (state) => state.waitingParticipants.waitingParticipants;
|
|
4061
4117
|
|
|
4118
|
+
const initialState = {
|
|
4119
|
+
isSwitching: false,
|
|
4120
|
+
raw: {},
|
|
4121
|
+
};
|
|
4122
|
+
const cameraEffectsSlice = createSlice({
|
|
4123
|
+
name: "cameraEffects",
|
|
4124
|
+
initialState,
|
|
4125
|
+
reducers: {
|
|
4126
|
+
cameraEffectsSwitching(state, action) {
|
|
4127
|
+
state.isSwitching = action.payload.isSwitching;
|
|
4128
|
+
},
|
|
4129
|
+
cameraEffectsCleared(state) {
|
|
4130
|
+
state.currentEffectId = null;
|
|
4131
|
+
state.setup = undefined;
|
|
4132
|
+
state.params = undefined;
|
|
4133
|
+
state.raw = {};
|
|
4134
|
+
state.error = undefined;
|
|
4135
|
+
state.isSwitching = false;
|
|
4136
|
+
},
|
|
4137
|
+
cameraEffectsUpdated(state, action) {
|
|
4138
|
+
const { effectId, setup, params, raw } = action.payload;
|
|
4139
|
+
state.currentEffectId = effectId;
|
|
4140
|
+
state.setup = setup;
|
|
4141
|
+
state.params = params;
|
|
4142
|
+
if (raw)
|
|
4143
|
+
state.raw = raw;
|
|
4144
|
+
state.error = undefined;
|
|
4145
|
+
state.isSwitching = false;
|
|
4146
|
+
},
|
|
4147
|
+
cameraEffectsError(state, action) {
|
|
4148
|
+
state.error = action.payload.error;
|
|
4149
|
+
state.isSwitching = false;
|
|
4150
|
+
},
|
|
4151
|
+
},
|
|
4152
|
+
});
|
|
4153
|
+
const { cameraEffectsSwitching, cameraEffectsCleared, cameraEffectsUpdated, cameraEffectsError } = cameraEffectsSlice.actions;
|
|
4154
|
+
const selectCameraEffectsRaw = (state) => state.cameraEffects.raw;
|
|
4155
|
+
const doCameraEffectsSwitchPreset = createAppAsyncThunk("cameraEffects/switchPreset", (_a, _b) => __awaiter(void 0, [_a, _b], void 0, function* ({ effectId, setup, params, allowSafari, }, { getState, dispatch, rejectWithValue }) {
|
|
4156
|
+
var _c, _d, _e;
|
|
4157
|
+
const state = getState();
|
|
4158
|
+
if (selectLocalMediaIsSwitchingStream(state)) {
|
|
4159
|
+
return;
|
|
4160
|
+
}
|
|
4161
|
+
dispatch(cameraEffectsSwitching({ isSwitching: true }));
|
|
4162
|
+
try {
|
|
4163
|
+
const raw = selectCameraEffectsRaw(state);
|
|
4164
|
+
const localStream = selectLocalMediaStream(state);
|
|
4165
|
+
if (!((_c = localStream === null || localStream === void 0 ? void 0 : localStream.getVideoTracks()) === null || _c === void 0 ? void 0 : _c[0])) {
|
|
4166
|
+
dispatch(cameraEffectsCleared());
|
|
4167
|
+
return;
|
|
4168
|
+
}
|
|
4169
|
+
if (!effectId) {
|
|
4170
|
+
if (raw.effectStream) {
|
|
4171
|
+
yield dispatch(doLocalStreamEffect({ effectStream: undefined, only: "video" }));
|
|
4172
|
+
}
|
|
4173
|
+
(_d = raw.stop) === null || _d === void 0 ? void 0 : _d.call(raw);
|
|
4174
|
+
dispatch(cameraEffectsCleared());
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
if (raw.tryUpdate) {
|
|
4178
|
+
const ok = yield raw.tryUpdate(effectId, Object.assign({}, (setup || {})), Object.assign({}, (params || {})));
|
|
4179
|
+
if (ok) {
|
|
4180
|
+
dispatch(cameraEffectsUpdated({ effectId, setup, params }));
|
|
4181
|
+
return;
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
if (raw.effectStream) {
|
|
4185
|
+
yield dispatch(doLocalStreamEffect({ effectStream: undefined, only: "video" }));
|
|
4186
|
+
(_e = raw.stop) === null || _e === void 0 ? void 0 : _e.call(raw);
|
|
4187
|
+
}
|
|
4188
|
+
let mod;
|
|
4189
|
+
try {
|
|
4190
|
+
mod = yield import('@whereby.com/camera-effects');
|
|
4191
|
+
}
|
|
4192
|
+
catch (_f) {
|
|
4193
|
+
throw new Error("@whereby.com/camera-effects is not installed. Add it as a dependency to enable camera effects.");
|
|
4194
|
+
}
|
|
4195
|
+
const { createEffectStream, getUsablePresets } = mod;
|
|
4196
|
+
const usable = getUsablePresets({ filter: () => true, options: { allowSafari } });
|
|
4197
|
+
if (!usable.includes(effectId)) {
|
|
4198
|
+
throw new Error(`Unknown or unsupported effect preset: ${effectId}`);
|
|
4199
|
+
}
|
|
4200
|
+
const { stream: effectStream, stop, tryUpdate, } = yield createEffectStream(localStream, effectId, setup, params);
|
|
4201
|
+
yield dispatch(doLocalStreamEffect({ effectStream, only: "video" }));
|
|
4202
|
+
dispatch(cameraEffectsUpdated({ effectId, setup, params, raw: { stop, tryUpdate, effectStream } }));
|
|
4203
|
+
}
|
|
4204
|
+
catch (error) {
|
|
4205
|
+
dispatch(cameraEffectsError({ error }));
|
|
4206
|
+
return rejectWithValue(error);
|
|
4207
|
+
}
|
|
4208
|
+
}));
|
|
4209
|
+
createAppAsyncThunk("cameraEffects/clear", (_1, _a) => __awaiter(void 0, [_1, _a], void 0, function* (_, { dispatch }) {
|
|
4210
|
+
yield dispatch(doCameraEffectsSwitchPreset({ effectId: null }));
|
|
4211
|
+
}));
|
|
4212
|
+
|
|
4062
4213
|
const IS_DEV = undefined === "true";
|
|
4063
4214
|
const appReducer = combineReducers({
|
|
4064
4215
|
app: appSlice.reducer,
|
|
4065
4216
|
authorization: authorizationSlice.reducer,
|
|
4066
4217
|
breakout: breakoutSlice.reducer,
|
|
4218
|
+
cameraEffects: cameraEffectsSlice.reducer,
|
|
4067
4219
|
chat: chatSlice.reducer,
|
|
4068
4220
|
cloudRecording: cloudRecordingSlice.reducer,
|
|
4069
4221
|
connectionMonitor: connectionMonitorSlice.reducer,
|
|
@@ -4733,6 +4885,28 @@ class RoomConnectionClient extends BaseClient {
|
|
|
4733
4885
|
reportStreamResolution(streamId, width, height) {
|
|
4734
4886
|
this.store.dispatch(doRtcReportStreamResolution({ streamId, width, height }));
|
|
4735
4887
|
}
|
|
4888
|
+
switchCameraEffect(effectId) {
|
|
4889
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4890
|
+
try {
|
|
4891
|
+
yield this.store.dispatch(doCameraEffectsSwitchPreset({ effectId }));
|
|
4892
|
+
}
|
|
4893
|
+
catch (error) {
|
|
4894
|
+
return Promise.reject(error);
|
|
4895
|
+
}
|
|
4896
|
+
return Promise.resolve();
|
|
4897
|
+
});
|
|
4898
|
+
}
|
|
4899
|
+
clearCameraEffect() {
|
|
4900
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4901
|
+
try {
|
|
4902
|
+
yield this.store.dispatch(doCameraEffectsSwitchPreset({ effectId: null }));
|
|
4903
|
+
}
|
|
4904
|
+
catch (error) {
|
|
4905
|
+
return Promise.reject(error);
|
|
4906
|
+
}
|
|
4907
|
+
return Promise.resolve();
|
|
4908
|
+
});
|
|
4909
|
+
}
|
|
4736
4910
|
destroy() {
|
|
4737
4911
|
super.destroy();
|
|
4738
4912
|
this.store.dispatch(doAppStop());
|
package/dist/legacy-esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import nodeBtoa from 'btoa';
|
|
2
|
-
import { assert, fromLocation, ServerSocket, getDeviceData, getStream, getUpdatedDevices, RtcManagerDispatcher, setClientProvider, subscribeIssues } from '@whereby.com/media';
|
|
2
|
+
import { assert, fromLocation, ServerSocket, getDeviceData, getStream, getUpdatedDevices, replaceTracksInStream, RtcManagerDispatcher, setClientProvider, subscribeIssues } from '@whereby.com/media';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
5
5
|
import { createListenerMiddleware, createSlice, createAction, createSelector, createAsyncThunk, isAnyOf, combineReducers, configureStore, addListener } from '@reduxjs/toolkit';
|
|
@@ -1145,9 +1145,9 @@ const createReactor = (selectors, callback) => {
|
|
|
1145
1145
|
});
|
|
1146
1146
|
};
|
|
1147
1147
|
|
|
1148
|
-
const coreVersion = "1.
|
|
1148
|
+
const coreVersion = "1.3.1";
|
|
1149
1149
|
|
|
1150
|
-
const initialState = {
|
|
1150
|
+
const initialState$1 = {
|
|
1151
1151
|
isNodeSdk: false,
|
|
1152
1152
|
isActive: false,
|
|
1153
1153
|
isDialIn: false,
|
|
@@ -1161,7 +1161,7 @@ const initialState = {
|
|
|
1161
1161
|
};
|
|
1162
1162
|
const appSlice = createSlice({
|
|
1163
1163
|
name: "app",
|
|
1164
|
-
initialState,
|
|
1164
|
+
initialState: initialState$1,
|
|
1165
1165
|
reducers: {
|
|
1166
1166
|
doAppStart: (state, action) => {
|
|
1167
1167
|
const url = new URL(action.payload.roomUrl);
|
|
@@ -1688,6 +1688,12 @@ const localMediaSlice = createSlice({
|
|
|
1688
1688
|
builder.addCase(doSwitchLocalStream.rejected, (state) => {
|
|
1689
1689
|
return Object.assign(Object.assign({}, state), { isSwitchingStream: false });
|
|
1690
1690
|
});
|
|
1691
|
+
builder.addCase(doLocalStreamEffect.fulfilled, (state, { payload }) => {
|
|
1692
|
+
if (!payload) {
|
|
1693
|
+
return state;
|
|
1694
|
+
}
|
|
1695
|
+
return Object.assign(Object.assign({}, state), { beforeEffectTracks: Object.assign(Object.assign({}, state.beforeEffectTracks), payload.beforeEffectTracks) });
|
|
1696
|
+
});
|
|
1691
1697
|
},
|
|
1692
1698
|
});
|
|
1693
1699
|
const { deviceBusy, setCurrentCameraDeviceId, setCurrentMicrophoneDeviceId, setCurrentSpeakerDeviceId, toggleCameraEnabled, toggleMicrophoneEnabled, toggleLowDataModeEnabled, setLocalMediaOptions, setLocalMediaStream, localMediaStopped, localStreamMetadataUpdated, } = localMediaSlice.actions;
|
|
@@ -1817,6 +1823,15 @@ const doSwitchLocalStream = createAppAsyncThunk("localMedia/doSwitchLocalStream"
|
|
|
1817
1823
|
if (!replaceStream) {
|
|
1818
1824
|
return;
|
|
1819
1825
|
}
|
|
1826
|
+
const beforeEffectTracks = selectLocalMediaBeforeEffectTracks(state);
|
|
1827
|
+
if (audioId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.audio)) {
|
|
1828
|
+
beforeEffectTracks.audio.stop();
|
|
1829
|
+
beforeEffectTracks.audio = undefined;
|
|
1830
|
+
}
|
|
1831
|
+
if (videoId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.video)) {
|
|
1832
|
+
beforeEffectTracks.video.stop();
|
|
1833
|
+
beforeEffectTracks.video = undefined;
|
|
1834
|
+
}
|
|
1820
1835
|
try {
|
|
1821
1836
|
const { replacedTracks } = yield getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: audioId === undefined ? false : audioId, videoId: videoId === undefined ? false : videoId, type: "exact" }), { replaceStream });
|
|
1822
1837
|
const deviceId = audioId || videoId;
|
|
@@ -1825,7 +1840,7 @@ const doSwitchLocalStream = createAppAsyncThunk("localMedia/doSwitchLocalStream"
|
|
|
1825
1840
|
deviceId,
|
|
1826
1841
|
}));
|
|
1827
1842
|
}
|
|
1828
|
-
return { replacedTracks };
|
|
1843
|
+
return { replacedTracks, beforeEffectTracks };
|
|
1829
1844
|
}
|
|
1830
1845
|
catch (error) {
|
|
1831
1846
|
console.error(error);
|
|
@@ -1876,6 +1891,46 @@ const doStopLocalMedia = createAppThunk(() => (dispatch, getState) => {
|
|
|
1876
1891
|
}
|
|
1877
1892
|
dispatch(localMediaStopped());
|
|
1878
1893
|
});
|
|
1894
|
+
const doLocalStreamEffect = createAppAsyncThunk("localMedia/doLocalStreamEffect", (_a, _b) => __awaiter(void 0, [_a, _b], void 0, function* ({ effectStream, only, stopBeforeTrack, }, { getState }) {
|
|
1895
|
+
var _c;
|
|
1896
|
+
const state = getState();
|
|
1897
|
+
let beforeEffectTracks = selectLocalMediaBeforeEffectTracks(state);
|
|
1898
|
+
const beforeTrack = beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks[only];
|
|
1899
|
+
if (!effectStream && !beforeTrack)
|
|
1900
|
+
return;
|
|
1901
|
+
try {
|
|
1902
|
+
const stream = selectLocalMediaStream(state);
|
|
1903
|
+
let replacedTracks = null;
|
|
1904
|
+
if (!stream) {
|
|
1905
|
+
throw new Error("No local media stream");
|
|
1906
|
+
}
|
|
1907
|
+
if (effectStream) {
|
|
1908
|
+
if (!beforeTrack) {
|
|
1909
|
+
beforeEffectTracks = {
|
|
1910
|
+
[only]: (_c = (only === "audio" ? stream === null || stream === void 0 ? void 0 : stream.getAudioTracks() : stream === null || stream === void 0 ? void 0 : stream.getVideoTracks())) === null || _c === void 0 ? void 0 : _c[0],
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
replacedTracks = replaceTracksInStream(stream, effectStream, only);
|
|
1914
|
+
}
|
|
1915
|
+
else if (!stopBeforeTrack) {
|
|
1916
|
+
replacedTracks = replaceTracksInStream(stream, beforeTrack ? new MediaStream([beforeTrack]) : new MediaStream(), only);
|
|
1917
|
+
beforeEffectTracks = {
|
|
1918
|
+
[only]: undefined,
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
else if (beforeTrack) {
|
|
1922
|
+
beforeEffectTracks = {
|
|
1923
|
+
[only]: undefined,
|
|
1924
|
+
};
|
|
1925
|
+
beforeTrack.stop();
|
|
1926
|
+
}
|
|
1927
|
+
return { effectStream, beforeEffectTracks, replacedTracks };
|
|
1928
|
+
}
|
|
1929
|
+
catch (error) {
|
|
1930
|
+
console.error("Error applying local stream effect", error);
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
}));
|
|
1879
1934
|
const selectBusyDeviceIds = (state) => state.localMedia.busyDeviceIds;
|
|
1880
1935
|
const selectCameraDeviceError = (state) => state.localMedia.cameraDeviceError;
|
|
1881
1936
|
const selectCurrentCameraDeviceId = (state) => state.localMedia.currentCameraDeviceId;
|
|
@@ -1896,6 +1951,7 @@ const selectLocalMediaStream = (state) => state.localMedia.stream;
|
|
|
1896
1951
|
const selectMicrophoneDeviceError = (state) => state.localMedia.microphoneDeviceError;
|
|
1897
1952
|
const selectLocalMediaStartError = (state) => state.localMedia.startError;
|
|
1898
1953
|
const selectLocalMediaIsSwitchingStream = (state) => state.localMedia.isSwitchingStream;
|
|
1954
|
+
const selectLocalMediaBeforeEffectTracks = (state) => state.localMedia.beforeEffectTracks;
|
|
1899
1955
|
const selectLocalMediaConstraintsOptions = createSelector(selectLocalMediaDevices, selectCurrentCameraDeviceId, selectCurrentMicrophoneDeviceId, selectIsLowDataModeEnabled, (devices, videoId, audioId, lowDataMode) => ({
|
|
1900
1956
|
devices,
|
|
1901
1957
|
videoId,
|
|
@@ -1992,7 +2048,7 @@ startAppListening({
|
|
|
1992
2048
|
},
|
|
1993
2049
|
});
|
|
1994
2050
|
startAppListening({
|
|
1995
|
-
matcher: isAnyOf(doStartLocalMedia.fulfilled, doUpdateDeviceList.fulfilled, doSwitchLocalStream.fulfilled, doSwitchLocalStream.rejected),
|
|
2051
|
+
matcher: isAnyOf(doStartLocalMedia.fulfilled, doUpdateDeviceList.fulfilled, doSwitchLocalStream.fulfilled, doSwitchLocalStream.rejected, doLocalStreamEffect.fulfilled),
|
|
1996
2052
|
effect: (_action, { dispatch, getState }) => {
|
|
1997
2053
|
const state = getState();
|
|
1998
2054
|
const stream = selectLocalMediaStream(state);
|
|
@@ -3043,7 +3099,7 @@ startAppListening({
|
|
|
3043
3099
|
},
|
|
3044
3100
|
});
|
|
3045
3101
|
startAppListening({
|
|
3046
|
-
|
|
3102
|
+
matcher: isAnyOf(doSwitchLocalStream.fulfilled, doLocalStreamEffect.fulfilled),
|
|
3047
3103
|
effect: ({ payload }, { getState }) => {
|
|
3048
3104
|
var _a;
|
|
3049
3105
|
const stream = selectLocalMediaStream(getState());
|
|
@@ -4059,11 +4115,107 @@ const doRejectWaitingParticipant = createRoomConnectedThunk((payload) => (dispat
|
|
|
4059
4115
|
});
|
|
4060
4116
|
const selectWaitingParticipants = (state) => state.waitingParticipants.waitingParticipants;
|
|
4061
4117
|
|
|
4118
|
+
const initialState = {
|
|
4119
|
+
isSwitching: false,
|
|
4120
|
+
raw: {},
|
|
4121
|
+
};
|
|
4122
|
+
const cameraEffectsSlice = createSlice({
|
|
4123
|
+
name: "cameraEffects",
|
|
4124
|
+
initialState,
|
|
4125
|
+
reducers: {
|
|
4126
|
+
cameraEffectsSwitching(state, action) {
|
|
4127
|
+
state.isSwitching = action.payload.isSwitching;
|
|
4128
|
+
},
|
|
4129
|
+
cameraEffectsCleared(state) {
|
|
4130
|
+
state.currentEffectId = null;
|
|
4131
|
+
state.setup = undefined;
|
|
4132
|
+
state.params = undefined;
|
|
4133
|
+
state.raw = {};
|
|
4134
|
+
state.error = undefined;
|
|
4135
|
+
state.isSwitching = false;
|
|
4136
|
+
},
|
|
4137
|
+
cameraEffectsUpdated(state, action) {
|
|
4138
|
+
const { effectId, setup, params, raw } = action.payload;
|
|
4139
|
+
state.currentEffectId = effectId;
|
|
4140
|
+
state.setup = setup;
|
|
4141
|
+
state.params = params;
|
|
4142
|
+
if (raw)
|
|
4143
|
+
state.raw = raw;
|
|
4144
|
+
state.error = undefined;
|
|
4145
|
+
state.isSwitching = false;
|
|
4146
|
+
},
|
|
4147
|
+
cameraEffectsError(state, action) {
|
|
4148
|
+
state.error = action.payload.error;
|
|
4149
|
+
state.isSwitching = false;
|
|
4150
|
+
},
|
|
4151
|
+
},
|
|
4152
|
+
});
|
|
4153
|
+
const { cameraEffectsSwitching, cameraEffectsCleared, cameraEffectsUpdated, cameraEffectsError } = cameraEffectsSlice.actions;
|
|
4154
|
+
const selectCameraEffectsRaw = (state) => state.cameraEffects.raw;
|
|
4155
|
+
const doCameraEffectsSwitchPreset = createAppAsyncThunk("cameraEffects/switchPreset", (_a, _b) => __awaiter(void 0, [_a, _b], void 0, function* ({ effectId, setup, params, allowSafari, }, { getState, dispatch, rejectWithValue }) {
|
|
4156
|
+
var _c, _d, _e;
|
|
4157
|
+
const state = getState();
|
|
4158
|
+
if (selectLocalMediaIsSwitchingStream(state)) {
|
|
4159
|
+
return;
|
|
4160
|
+
}
|
|
4161
|
+
dispatch(cameraEffectsSwitching({ isSwitching: true }));
|
|
4162
|
+
try {
|
|
4163
|
+
const raw = selectCameraEffectsRaw(state);
|
|
4164
|
+
const localStream = selectLocalMediaStream(state);
|
|
4165
|
+
if (!((_c = localStream === null || localStream === void 0 ? void 0 : localStream.getVideoTracks()) === null || _c === void 0 ? void 0 : _c[0])) {
|
|
4166
|
+
dispatch(cameraEffectsCleared());
|
|
4167
|
+
return;
|
|
4168
|
+
}
|
|
4169
|
+
if (!effectId) {
|
|
4170
|
+
if (raw.effectStream) {
|
|
4171
|
+
yield dispatch(doLocalStreamEffect({ effectStream: undefined, only: "video" }));
|
|
4172
|
+
}
|
|
4173
|
+
(_d = raw.stop) === null || _d === void 0 ? void 0 : _d.call(raw);
|
|
4174
|
+
dispatch(cameraEffectsCleared());
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
if (raw.tryUpdate) {
|
|
4178
|
+
const ok = yield raw.tryUpdate(effectId, Object.assign({}, (setup || {})), Object.assign({}, (params || {})));
|
|
4179
|
+
if (ok) {
|
|
4180
|
+
dispatch(cameraEffectsUpdated({ effectId, setup, params }));
|
|
4181
|
+
return;
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
if (raw.effectStream) {
|
|
4185
|
+
yield dispatch(doLocalStreamEffect({ effectStream: undefined, only: "video" }));
|
|
4186
|
+
(_e = raw.stop) === null || _e === void 0 ? void 0 : _e.call(raw);
|
|
4187
|
+
}
|
|
4188
|
+
let mod;
|
|
4189
|
+
try {
|
|
4190
|
+
mod = yield import('@whereby.com/camera-effects');
|
|
4191
|
+
}
|
|
4192
|
+
catch (_f) {
|
|
4193
|
+
throw new Error("@whereby.com/camera-effects is not installed. Add it as a dependency to enable camera effects.");
|
|
4194
|
+
}
|
|
4195
|
+
const { createEffectStream, getUsablePresets } = mod;
|
|
4196
|
+
const usable = getUsablePresets({ filter: () => true, options: { allowSafari } });
|
|
4197
|
+
if (!usable.includes(effectId)) {
|
|
4198
|
+
throw new Error(`Unknown or unsupported effect preset: ${effectId}`);
|
|
4199
|
+
}
|
|
4200
|
+
const { stream: effectStream, stop, tryUpdate, } = yield createEffectStream(localStream, effectId, setup, params);
|
|
4201
|
+
yield dispatch(doLocalStreamEffect({ effectStream, only: "video" }));
|
|
4202
|
+
dispatch(cameraEffectsUpdated({ effectId, setup, params, raw: { stop, tryUpdate, effectStream } }));
|
|
4203
|
+
}
|
|
4204
|
+
catch (error) {
|
|
4205
|
+
dispatch(cameraEffectsError({ error }));
|
|
4206
|
+
return rejectWithValue(error);
|
|
4207
|
+
}
|
|
4208
|
+
}));
|
|
4209
|
+
createAppAsyncThunk("cameraEffects/clear", (_1, _a) => __awaiter(void 0, [_1, _a], void 0, function* (_, { dispatch }) {
|
|
4210
|
+
yield dispatch(doCameraEffectsSwitchPreset({ effectId: null }));
|
|
4211
|
+
}));
|
|
4212
|
+
|
|
4062
4213
|
const IS_DEV = undefined === "true";
|
|
4063
4214
|
const appReducer = combineReducers({
|
|
4064
4215
|
app: appSlice.reducer,
|
|
4065
4216
|
authorization: authorizationSlice.reducer,
|
|
4066
4217
|
breakout: breakoutSlice.reducer,
|
|
4218
|
+
cameraEffects: cameraEffectsSlice.reducer,
|
|
4067
4219
|
chat: chatSlice.reducer,
|
|
4068
4220
|
cloudRecording: cloudRecordingSlice.reducer,
|
|
4069
4221
|
connectionMonitor: connectionMonitorSlice.reducer,
|
|
@@ -4733,6 +4885,28 @@ class RoomConnectionClient extends BaseClient {
|
|
|
4733
4885
|
reportStreamResolution(streamId, width, height) {
|
|
4734
4886
|
this.store.dispatch(doRtcReportStreamResolution({ streamId, width, height }));
|
|
4735
4887
|
}
|
|
4888
|
+
switchCameraEffect(effectId) {
|
|
4889
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4890
|
+
try {
|
|
4891
|
+
yield this.store.dispatch(doCameraEffectsSwitchPreset({ effectId }));
|
|
4892
|
+
}
|
|
4893
|
+
catch (error) {
|
|
4894
|
+
return Promise.reject(error);
|
|
4895
|
+
}
|
|
4896
|
+
return Promise.resolve();
|
|
4897
|
+
});
|
|
4898
|
+
}
|
|
4899
|
+
clearCameraEffect() {
|
|
4900
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4901
|
+
try {
|
|
4902
|
+
yield this.store.dispatch(doCameraEffectsSwitchPreset({ effectId: null }));
|
|
4903
|
+
}
|
|
4904
|
+
catch (error) {
|
|
4905
|
+
return Promise.reject(error);
|
|
4906
|
+
}
|
|
4907
|
+
return Promise.resolve();
|
|
4908
|
+
});
|
|
4909
|
+
}
|
|
4736
4910
|
destroy() {
|
|
4737
4911
|
super.destroy();
|
|
4738
4912
|
this.store.dispatch(doAppStop());
|