refactor recording and stuff
This commit is contained in:
parent
1e9f6aeaed
commit
96aa986e08
5 changed files with 82 additions and 22 deletions
1
Jenkinsfile
vendored
1
Jenkinsfile
vendored
|
@ -70,6 +70,7 @@ pipeline {
|
||||||
steps {
|
steps {
|
||||||
sshagent(credentials: ['ury']) {
|
sshagent(credentials: ['ury']) {
|
||||||
sh 'scp -v -o StrictHostKeyChecking=no server.py liquidsoap@dolby.ury:/opt/webstudioserver/server.py'
|
sh 'scp -v -o StrictHostKeyChecking=no server.py liquidsoap@dolby.ury:/opt/webstudioserver/server.py'
|
||||||
|
sh 'scp -v -o StrictHostKeyChecking=no requirements.txt liquidsoap@dolby.ury:/opt/webstudioserver/requirements.txt'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,12 @@ import * as NavbarState from "../navbar/state";
|
||||||
import { ConnectionStateEnum, Streamer } from "./streamer";
|
import { ConnectionStateEnum, Streamer } from "./streamer";
|
||||||
import { RecordingStreamer } from "./recording_streamer";
|
import { RecordingStreamer } from "./recording_streamer";
|
||||||
|
|
||||||
export let streamer: Streamer | null = null;
|
export let streamer: WebRTCStreamer | null = null;
|
||||||
|
|
||||||
interface BroadcastState {
|
interface BroadcastState {
|
||||||
tracklisting: boolean;
|
tracklisting: boolean;
|
||||||
connectionState: ConnectionStateEnum;
|
connectionState: ConnectionStateEnum;
|
||||||
|
recordingState: ConnectionStateEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
const broadcastState = createSlice({
|
const broadcastState = createSlice({
|
||||||
|
@ -19,6 +20,7 @@ const broadcastState = createSlice({
|
||||||
initialState: {
|
initialState: {
|
||||||
tracklisting: false,
|
tracklisting: false,
|
||||||
connectionState: "NOT_CONNECTED",
|
connectionState: "NOT_CONNECTED",
|
||||||
|
recordingState: "NOT_CONNECTED"
|
||||||
} as BroadcastState,
|
} as BroadcastState,
|
||||||
reducers: {
|
reducers: {
|
||||||
toggleTracklisting(state) {
|
toggleTracklisting(state) {
|
||||||
|
@ -27,6 +29,9 @@ const broadcastState = createSlice({
|
||||||
setConnectionState(state, action: PayloadAction<ConnectionStateEnum>) {
|
setConnectionState(state, action: PayloadAction<ConnectionStateEnum>) {
|
||||||
state.connectionState = action.payload;
|
state.connectionState = action.payload;
|
||||||
},
|
},
|
||||||
|
setRecordingState(state, action: PayloadAction<ConnectionStateEnum>) {
|
||||||
|
state.recordingState = action.payload;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -71,34 +76,46 @@ export function sendTracklistStart(trackid: number): Promise<TrackListItem> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const RECORD = false;
|
export const startStreaming = (): AppThunk => async (dispatch, getState) => {
|
||||||
|
if (!getState().session.userCanBroadcast) {
|
||||||
export const connect = (): AppThunk => async (dispatch, getState) => {
|
dispatch(
|
||||||
if (RECORD) {
|
NavbarState.showAlert({
|
||||||
streamer = new RecordingStreamer(MixerState.destination.stream);
|
color: "warning",
|
||||||
} else {
|
content: "You are not WebStudio Trained and cannot go live.",
|
||||||
if (!getState().session.userCanBroadcast) {
|
closure: 7000,
|
||||||
dispatch(
|
})
|
||||||
NavbarState.showAlert({
|
);
|
||||||
color: "warning",
|
return;
|
||||||
content: "You are not WebStudio Trained and cannot go live.",
|
|
||||||
closure: 7000,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
streamer = new WebRTCStreamer(MixerState.destination.stream);
|
|
||||||
}
|
}
|
||||||
|
streamer = new WebRTCStreamer(MixerState.destination.stream);
|
||||||
streamer.addConnectionStateListener((state) => {
|
streamer.addConnectionStateListener((state) => {
|
||||||
dispatch(broadcastState.actions.setConnectionState(state));
|
dispatch(broadcastState.actions.setConnectionState(state));
|
||||||
});
|
});
|
||||||
await streamer.start();
|
await streamer.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const disconnect = (): AppThunk => async (dispatch) => {
|
export const stopStreaming = (): AppThunk => async (dispatch) => {
|
||||||
if (streamer) {
|
if (streamer) {
|
||||||
await streamer.stop();
|
await streamer.stop();
|
||||||
} else {
|
} else {
|
||||||
console.warn("disconnect called with no streamer!");
|
console.warn("disconnect called with no streamer!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let recorder: RecordingStreamer;
|
||||||
|
|
||||||
|
export const startRecording = (): AppThunk => async dispatch => {
|
||||||
|
recorder = new RecordingStreamer(MixerState.destination.stream);
|
||||||
|
recorder.addConnectionStateListener((state) => {
|
||||||
|
dispatch(broadcastState.actions.setConnectionState(state));
|
||||||
|
});
|
||||||
|
await recorder.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
export const stopRecording = (): AppThunk => async dispatch => {
|
||||||
|
if (recorder) {
|
||||||
|
await recorder.stop();
|
||||||
|
} else {
|
||||||
|
console.warn("stopRecording called with no recorder!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ export function NavBar() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const sessionState = useSelector((state: RootState) => state.session);
|
const sessionState = useSelector((state: RootState) => state.session);
|
||||||
const broadcastState = useSelector((state: RootState) => state.broadcast);
|
const broadcastState = useSelector((state: RootState) => state.broadcast);
|
||||||
|
const settings = useSelector((state: RootState) => state.settings);
|
||||||
const redirect_url = encodeURIComponent(window.location.toString());
|
const redirect_url = encodeURIComponent(window.location.toString());
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -42,6 +43,25 @@ export function NavBar() {
|
||||||
: "Not Tracklisting"}{" "}
|
: "Not Tracklisting"}{" "}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
{settings.enableRecording && (
|
||||||
|
<li className="nav-item nav-link">
|
||||||
|
<button
|
||||||
|
className=""
|
||||||
|
onClick={() =>
|
||||||
|
dispatch(
|
||||||
|
broadcastState.recordingState ===
|
||||||
|
"NOT_CONNECTED"
|
||||||
|
? BroadcastState.startRecording()
|
||||||
|
: BroadcastState.stopRecording()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{broadcastState.recordingState === "NOT_CONNECTED"
|
||||||
|
? "Start Recording"
|
||||||
|
: "Stop Recording"}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
<li className="nav-item nav-link">
|
<li className="nav-item nav-link">
|
||||||
<button
|
<button
|
||||||
className=""
|
className=""
|
||||||
|
@ -49,8 +69,8 @@ export function NavBar() {
|
||||||
dispatch(
|
dispatch(
|
||||||
broadcastState.connectionState ===
|
broadcastState.connectionState ===
|
||||||
"NOT_CONNECTED"
|
"NOT_CONNECTED"
|
||||||
? BroadcastState.connect()
|
? BroadcastState.startStreaming()
|
||||||
: BroadcastState.disconnect()
|
: BroadcastState.stopStreaming()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
@ -27,6 +27,24 @@ export function AdvancedTab() {
|
||||||
Show showplan debugging information
|
Show showplan debugging information
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-check">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
checked={settings.enableRecording}
|
||||||
|
onChange={(e) =>
|
||||||
|
dispatch(
|
||||||
|
changeSetting({
|
||||||
|
key: "enableRecording",
|
||||||
|
val: e.target.checked,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label">
|
||||||
|
Enable recording
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,15 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
interface Settings {
|
interface Settings {
|
||||||
showDebugInfo: boolean;
|
showDebugInfo: boolean;
|
||||||
|
enableRecording: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsState = createSlice({
|
const settingsState = createSlice({
|
||||||
name: "settings",
|
name: "settings",
|
||||||
initialState: {} as Settings,
|
initialState: {
|
||||||
|
showDebugInfo: false,
|
||||||
|
enableRecording: false
|
||||||
|
} as Settings,
|
||||||
reducers: {
|
reducers: {
|
||||||
changeSetting<K extends keyof Settings>(state: Settings, action: PayloadAction<{ key: K, val: Settings[K] }>) {
|
changeSetting<K extends keyof Settings>(state: Settings, action: PayloadAction<{ key: K, val: Settings[K] }>) {
|
||||||
state[action.payload.key] = action.payload.val;
|
state[action.payload.key] = action.payload.val;
|
||||||
|
|
Loading…
Reference in a new issue