First pass at more recording types, updated README
This commit is contained in:
parent
01fca4b98d
commit
16d259ccc4
|
|
@ -6,14 +6,14 @@
|
||||||
|
|
||||||
## What does this demo do?
|
## What does this demo do?
|
||||||
|
|
||||||
- Use [startRecording](https://docs.daily.co/reference#%EF%B8%8F-startrecording) to create a video and audio recording of your call. You can read more about Daily call recording (and the different modes and types) [here](https://docs.daily.co/reference#recordings)
|
- Use [startRecording](https://docs.daily.co/reference#%EF%B8%8F-startrecording) to create a video and audio recording of your call. You can read more about Daily call recording (and the different modes and types) [here](https://docs.daily.co/guides/recording-calls-with-the-daily-api)
|
||||||
- Supports both `cloud` and `local` recording modes (specified when creating the room or managed using the Daily dashboard)
|
- Supports `cloud`, `cloud-beta`, `local`, and `rtp-tracks` recording modes (specified when creating the room or managed using the Daily dashboard). _Heads up: if recording on mobile devices or Safari, then `cloud-beta` must be the specified mode._
|
||||||
- Coming soon: support different recording layouts / composites
|
- Coming soon: support different recording layouts / composites
|
||||||
- Coming soon: use the Daily REST API to retrieve a list of cloud recordings for the currently active room
|
- Coming soon: use the Daily REST API to retrieve a list of cloud recordings for the currently active room
|
||||||
|
|
||||||
**To turn on recording, you need to be on the Scale plan. There is also a per minute recording fee for cloud recording.**
|
**To turn on recording, you need to be on the Scale plan. There is also a per minute recording fee for cloud recording.**
|
||||||
|
|
||||||
Please note: this demo is not currently mobile optimised
|
Please note: this demo is not currently mobile optimised.
|
||||||
|
|
||||||
### Getting started
|
### Getting started
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import {
|
||||||
RECORDING_RECORDING,
|
RECORDING_RECORDING,
|
||||||
RECORDING_SAVED,
|
RECORDING_SAVED,
|
||||||
RECORDING_TYPE_CLOUD,
|
RECORDING_TYPE_CLOUD,
|
||||||
|
RECORDING_TYPE_CLOUD_BETA,
|
||||||
|
RECORDING_TYPE_RTP_TRACKS,
|
||||||
RECORDING_UPLOADING,
|
RECORDING_UPLOADING,
|
||||||
useRecording,
|
useRecording,
|
||||||
} from '../contexts/RecordingProvider';
|
} from '../contexts/RecordingProvider';
|
||||||
|
|
@ -105,7 +107,9 @@ export const RecordingModal = () => {
|
||||||
<p>Recording started: {recordingStartedDate.toString()}</p>
|
<p>Recording started: {recordingStartedDate.toString()}</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{enableRecording === RECORDING_TYPE_CLOUD && (
|
{[RECORDING_TYPE_CLOUD, RECORDING_TYPE_CLOUD_BETA].includes(
|
||||||
|
enableRecording
|
||||||
|
) && (
|
||||||
<>
|
<>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
|
@ -115,6 +119,24 @@ export const RecordingModal = () => {
|
||||||
</p>
|
</p>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{enableRecording === RECORDING_TYPE_RTP_TRACKS && (
|
||||||
|
<>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<p>
|
||||||
|
rtp-tracks recordings can be accessed via the Daily API. See the{' '}
|
||||||
|
<a
|
||||||
|
href="https://docs.daily.co/guides/recording-calls-with-the-daily-api#retrieve-individual-tracks-from-rtp-tracks-recordings"
|
||||||
|
noreferrer
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Daily recording guide
|
||||||
|
</a>{' '}
|
||||||
|
for details.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,10 @@ export const RECORDING_COUNTDOWN_3 = 'starting3';
|
||||||
export const RECORDING_IDLE = 'idle';
|
export const RECORDING_IDLE = 'idle';
|
||||||
|
|
||||||
export const RECORDING_TYPE_CLOUD = 'cloud';
|
export const RECORDING_TYPE_CLOUD = 'cloud';
|
||||||
|
export const RECORDING_TYPE_CLOUD_BETA = 'cloud-beta';
|
||||||
export const RECORDING_TYPE_LOCAL = 'local';
|
export const RECORDING_TYPE_LOCAL = 'local';
|
||||||
|
export const RECORDING_TYPE_OUTPUT_BYTE_STREAM = 'output-byte-stream';
|
||||||
|
export const RECORDING_TYPE_RTP_TRACKS = 'rtp-tracks';
|
||||||
|
|
||||||
const RecordingContext = createContext({
|
const RecordingContext = createContext({
|
||||||
isRecordingLocally: false,
|
isRecordingLocally: false,
|
||||||
|
|
@ -37,8 +40,12 @@ const RecordingContext = createContext({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RecordingProvider = ({ children }) => {
|
export const RecordingProvider = ({ children }) => {
|
||||||
const { callObject, enableRecording, startCloudRecording, state } =
|
const {
|
||||||
useCallState();
|
callObject,
|
||||||
|
enableRecording,
|
||||||
|
startCloudRecording,
|
||||||
|
state,
|
||||||
|
} = useCallState();
|
||||||
const { participants } = useParticipants();
|
const { participants } = useParticipants();
|
||||||
const [recordingStartedDate, setRecordingStartedDate] = useState(null);
|
const [recordingStartedDate, setRecordingStartedDate] = useState(null);
|
||||||
const [recordingState, setRecordingState] = useState(RECORDING_IDLE);
|
const [recordingState, setRecordingState] = useState(RECORDING_IDLE);
|
||||||
|
|
@ -85,11 +92,26 @@ export const RecordingProvider = ({ children }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The 'recording-data' event is emitted when an output-byte-stream recording has started
|
||||||
|
const handleRecordingData = async (ev) => {
|
||||||
|
try {
|
||||||
|
console.log('got data', ev);
|
||||||
|
await window.writer.write(ev.data);
|
||||||
|
if (ev.finished) {
|
||||||
|
console.log('closing!');
|
||||||
|
window.writer.close();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleRecordingUploadCompleted = () => {
|
const handleRecordingUploadCompleted = () => {
|
||||||
setRecordingState(RECORDING_SAVED);
|
setRecordingState(RECORDING_SAVED);
|
||||||
};
|
};
|
||||||
|
|
||||||
callObject.on('app-message', handleAppMessage);
|
callObject.on('app-message', handleAppMessage);
|
||||||
|
callObject.on('recording-data', handleRecordingData);
|
||||||
callObject.on('recording-upload-completed', handleRecordingUploadCompleted);
|
callObject.on('recording-upload-completed', handleRecordingUploadCompleted);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -263,10 +285,13 @@ export const RecordingProvider = ({ children }) => {
|
||||||
if (recordingState === RECORDING_RECORDING) {
|
if (recordingState === RECORDING_RECORDING) {
|
||||||
switch (enableRecording) {
|
switch (enableRecording) {
|
||||||
case RECORDING_TYPE_LOCAL:
|
case RECORDING_TYPE_LOCAL:
|
||||||
|
case RECORDING_TYPE_OUTPUT_BYTE_STREAM:
|
||||||
setRecordingState(RECORDING_SAVED);
|
setRecordingState(RECORDING_SAVED);
|
||||||
setIsRecordingLocally(false);
|
setIsRecordingLocally(false);
|
||||||
break;
|
break;
|
||||||
case RECORDING_TYPE_CLOUD:
|
case RECORDING_TYPE_CLOUD:
|
||||||
|
case RECORDING_TYPE_CLOUD_BETA:
|
||||||
|
case RECORDING_TYPE_RTP_TRACKS:
|
||||||
setRecordingState(RECORDING_UPLOADING);
|
setRecordingState(RECORDING_UPLOADING);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* ---
|
* ---
|
||||||
* Configures the general state of a Daily call, such as which features
|
* Configures the general state of a Daily call, such as which features
|
||||||
* to enable, as well as instantiate the 'call machine' hook responsible
|
* to enable, as well as instantiate the 'call machine' hook responsible
|
||||||
* fir the overaching call loop (joining, leaving, etc)
|
* for the overaching call loop (joining, leaving, etc)
|
||||||
*/
|
*/
|
||||||
import React, {
|
import React, {
|
||||||
createContext,
|
createContext,
|
||||||
|
|
@ -60,19 +60,22 @@ export const CallProvider = ({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const browser = Bowser.parse(window.navigator.userAgent);
|
const browser = Bowser.parse(window.navigator.userAgent);
|
||||||
|
const recordingType =
|
||||||
|
roomConfig?.tokenConfig?.enable_recording ??
|
||||||
|
roomConfig?.config?.enable_recording;
|
||||||
|
|
||||||
|
// Mobile and Safari recordings are only supported under the 'cloud-beta' type
|
||||||
const supportsRecording =
|
const supportsRecording =
|
||||||
browser.platform.type === 'desktop' && browser.engine.name === 'Blink';
|
((browser.platform.type !== 'desktop' ||
|
||||||
// recording and screen sharing is hidden in owner_only_broadcast for non-owners
|
browser.engine.name !== 'Blink') &&
|
||||||
|
recordingType === 'cloud-beta') ||
|
||||||
|
(browser.platform.type === 'desktop' &&
|
||||||
|
browser.engine.name === 'Blink');
|
||||||
if (supportsRecording) {
|
if (supportsRecording) {
|
||||||
const recordingType =
|
setEnableRecording(recordingType);
|
||||||
roomConfig?.tokenConfig?.enable_recording ??
|
setStartCloudRecording(
|
||||||
roomConfig?.config?.enable_recording;
|
roomConfig?.tokenConfig?.start_cloud_recording ?? false
|
||||||
if (['local', 'cloud'].includes(recordingType)) {
|
);
|
||||||
setEnableRecording(recordingType);
|
|
||||||
setStartCloudRecording(
|
|
||||||
roomConfig?.tokenConfig?.start_cloud_recording ?? false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
updateRoomConfigState();
|
updateRoomConfigState();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue