mirror of https://github.com/OpenVidu/openvidu.git
ov-components: enhance recording status management and elapsed time calculation
parent
cff617b0c3
commit
8ce155df6a
|
@ -47,6 +47,7 @@ import {
|
||||||
Track
|
Track
|
||||||
} from 'livekit-client';
|
} from 'livekit-client';
|
||||||
import { ParticipantLeftEvent, ParticipantLeftReason, ParticipantModel } from '../../models/participant.model';
|
import { ParticipantLeftEvent, ParticipantLeftReason, ParticipantModel } from '../../models/participant.model';
|
||||||
|
import { RecordingStatus } from '../../models/recording.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
@ -456,7 +457,8 @@ export class SessionComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.recordingService.setRecordingList(recordingList);
|
this.recordingService.setRecordingList(recordingList);
|
||||||
if (isRecordingStarted) {
|
if (isRecordingStarted) {
|
||||||
this.recordingService.setRecordingStarted();
|
const recordingActive = recordingList.find((recording) => recording.status === RecordingStatus.STARTED);
|
||||||
|
this.recordingService.setRecordingStarted(recordingActive);
|
||||||
}
|
}
|
||||||
if (isBroadcastingStarted) {
|
if (isBroadcastingStarted) {
|
||||||
this.broadcastingService.setBroadcastingStarted(broadcastingId);
|
this.broadcastingService.setBroadcastingStarted(broadcastingId);
|
||||||
|
|
|
@ -15,87 +15,92 @@ export class RecordingService {
|
||||||
*/
|
*/
|
||||||
recordingStatusObs: Observable<RecordingStatusInfo>;
|
recordingStatusObs: Observable<RecordingStatusInfo>;
|
||||||
private recordingTimeInterval: NodeJS.Timeout;
|
private recordingTimeInterval: NodeJS.Timeout;
|
||||||
|
private recordingStartTimestamp: number | null = null;
|
||||||
|
|
||||||
private recordingStatus = <BehaviorSubject<RecordingStatusInfo>>new BehaviorSubject({
|
private recordingStatus = <BehaviorSubject<RecordingStatusInfo>>new BehaviorSubject({
|
||||||
status: RecordingStatus.STOPPED,
|
status: RecordingStatus.STOPPED,
|
||||||
recordingList: [] as RecordingInfo[],
|
recordingList: [] as RecordingInfo[],
|
||||||
recordingElapsedTime: new Date(0, 0, 0, 0, 0, 0, 0)
|
recordingElapsedTime: new Date(0, 0, 0, 0, 0, 0),
|
||||||
});
|
});
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
constructor(private actionService: ActionService, private libService: OpenViduComponentsConfigService, private loggerService: LoggerService) {
|
constructor(
|
||||||
|
private actionService: ActionService,
|
||||||
|
private libService: OpenViduComponentsConfigService,
|
||||||
|
private loggerService: LoggerService
|
||||||
|
) {
|
||||||
this.log = this.loggerService.get('RecordingService');
|
this.log = this.loggerService.get('RecordingService');
|
||||||
this.recordingStatusObs = this.recordingStatus.asObservable();
|
this.recordingStatusObs = this.recordingStatus.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Initializes the recording status with the given parameters and the timer to calculate the elapsed time.
|
||||||
* @internal
|
* @internal
|
||||||
* @param event
|
|
||||||
*/
|
*/
|
||||||
setRecordingStarted(recordingInfo?: RecordingInfo) {
|
setRecordingStarted(recordingInfo?: RecordingInfo, startTimestamp?: number) {
|
||||||
this.startRecordingTime();
|
// Register the start timestamp of the recording
|
||||||
const { recordingElapsedTime, recordingList } = this.recordingStatus.getValue();
|
// to calculate the elapsed time
|
||||||
|
debugger
|
||||||
|
this.recordingStartTimestamp = recordingInfo?.startedAt || Date.now();
|
||||||
|
|
||||||
|
// Initialize the recording elapsed time
|
||||||
|
this.startRecordingTimer();
|
||||||
|
|
||||||
|
const { recordingList } = this.recordingStatus.getValue();
|
||||||
|
let updatedRecordingList = [...recordingList];
|
||||||
|
|
||||||
if (recordingInfo) {
|
if (recordingInfo) {
|
||||||
const existingRecordingIndex = recordingList.findIndex((recording) => recording.id === recordingInfo.id);
|
const existingIndex = updatedRecordingList.findIndex((recording) => recording.id === recordingInfo.id);
|
||||||
if (existingRecordingIndex !== -1) {
|
if (existingIndex !== -1) {
|
||||||
// Replace existing recording info
|
// Replace existing recording info
|
||||||
recordingList[existingRecordingIndex] = recordingInfo;
|
updatedRecordingList[existingIndex] = recordingInfo;
|
||||||
} else {
|
} else {
|
||||||
// Add new recording info
|
// Add new recording info
|
||||||
recordingList.unshift(recordingInfo);
|
updatedRecordingList = [recordingInfo, ...updatedRecordingList];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const statusInfo: RecordingStatusInfo = {
|
const recordingElapsedTime = new Date(0, 0, 0, 0, 0, 0);
|
||||||
status: RecordingStatus.STARTED,
|
if (startTimestamp) {
|
||||||
recordingList,
|
const elapsedSeconds = Math.floor((Date.now() - startTimestamp) / 1000);
|
||||||
recordingElapsedTime
|
recordingElapsedTime.setSeconds(elapsedSeconds);
|
||||||
};
|
|
||||||
this.updateStatus(statusInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a recording from the recording list.
|
|
||||||
*
|
|
||||||
* @param rec - The recording to be deleted.
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
deleteRecording(rec: RecordingInfo) {
|
|
||||||
const { recordingList } = this.recordingStatus.getValue();
|
|
||||||
const index = recordingList.findIndex((recording) => recording.id === rec.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
recordingList.splice(index, 1);
|
|
||||||
this.updateStatus({
|
this.updateStatus({
|
||||||
status: this.recordingStatus.getValue().status,
|
status: RecordingStatus.STARTED,
|
||||||
recordingList,
|
recordingList: updatedRecordingList,
|
||||||
recordingElapsedTime: this.recordingStatus.getValue().recordingElapsedTime
|
recordingElapsedTime
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Stops the recording timer and updates the recording status to **stopped**.
|
||||||
* @internal
|
* @internal
|
||||||
* @param event
|
|
||||||
*/
|
*/
|
||||||
setRecordingStopped(recordingInfo?: RecordingInfo) {
|
setRecordingStopped(recordingInfo?: RecordingInfo) {
|
||||||
this.stopRecordingTime();
|
this.stopRecordingTimer();
|
||||||
const { recordingElapsedTime, recordingList } = this.recordingStatus.getValue();
|
const { recordingList } = this.recordingStatus.getValue();
|
||||||
|
let updatedRecordingList = [...recordingList];
|
||||||
|
|
||||||
|
// Update the recording list with the new recording info
|
||||||
if (recordingInfo) {
|
if (recordingInfo) {
|
||||||
const existingRecordingIndex = recordingList.findIndex((recording) => recording.id === recordingInfo.id);
|
const existingIndex = updatedRecordingList.findIndex((recording) => recording.id === recordingInfo.id);
|
||||||
if (existingRecordingIndex !== -1) {
|
if (existingIndex !== -1) {
|
||||||
// Replace existing recording info with the new one
|
updatedRecordingList[existingIndex] = recordingInfo;
|
||||||
recordingList[existingRecordingIndex] = recordingInfo;
|
|
||||||
} else {
|
} else {
|
||||||
recordingList.unshift(recordingInfo);
|
updatedRecordingList = [recordingInfo, ...updatedRecordingList];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const statusInfo: RecordingStatusInfo = {
|
|
||||||
|
this.updateStatus({
|
||||||
status: RecordingStatus.STOPPED,
|
status: RecordingStatus.STOPPED,
|
||||||
recordingList,
|
recordingList: updatedRecordingList,
|
||||||
recordingElapsedTime
|
recordingElapsedTime: new Date(0, 0, 0, 0, 0, 0)
|
||||||
};
|
});
|
||||||
this.updateStatus(statusInfo);
|
|
||||||
|
this.recordingStartTimestamp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,12 +109,11 @@ export class RecordingService {
|
||||||
*/
|
*/
|
||||||
setRecordingStarting() {
|
setRecordingStarting() {
|
||||||
const { recordingList, recordingElapsedTime } = this.recordingStatus.getValue();
|
const { recordingList, recordingElapsedTime } = this.recordingStatus.getValue();
|
||||||
const statusInfo: RecordingStatusInfo = {
|
this.updateStatus({
|
||||||
status: RecordingStatus.STARTING,
|
status: RecordingStatus.STARTING,
|
||||||
recordingList,
|
recordingList,
|
||||||
recordingElapsedTime
|
recordingElapsedTime
|
||||||
};
|
});
|
||||||
this.updateStatus(statusInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +121,7 @@ export class RecordingService {
|
||||||
* @param error
|
* @param error
|
||||||
*/
|
*/
|
||||||
setRecordingFailed(error: string) {
|
setRecordingFailed(error: string) {
|
||||||
this.stopRecordingTime();
|
this.stopRecordingTimer();
|
||||||
const { recordingElapsedTime, recordingList } = this.recordingStatus.getValue();
|
const { recordingElapsedTime, recordingList } = this.recordingStatus.getValue();
|
||||||
const statusInfo: RecordingStatusInfo = {
|
const statusInfo: RecordingStatusInfo = {
|
||||||
status: RecordingStatus.FAILED,
|
status: RecordingStatus.FAILED,
|
||||||
|
@ -134,12 +138,12 @@ export class RecordingService {
|
||||||
*/
|
*/
|
||||||
setRecordingStopping() {
|
setRecordingStopping() {
|
||||||
const { recordingElapsedTime, recordingList } = this.recordingStatus.getValue();
|
const { recordingElapsedTime, recordingList } = this.recordingStatus.getValue();
|
||||||
const statusInfo: RecordingStatusInfo = {
|
|
||||||
|
this.updateStatus({
|
||||||
status: RecordingStatus.STOPPING,
|
status: RecordingStatus.STOPPING,
|
||||||
recordingList,
|
recordingList,
|
||||||
recordingElapsedTime
|
recordingElapsedTime
|
||||||
};
|
});
|
||||||
this.updateStatus(statusInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,10 +178,29 @@ export class RecordingService {
|
||||||
view: window
|
view: window
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
setTimeout(() => {
|
|
||||||
// For Firefox it is necessary to delay revoking the ObjectURL
|
// For Firefox it is necessary to delay revoking the ObjectURL
|
||||||
link.remove();
|
setTimeout(() => link.remove(), 100);
|
||||||
}, 100);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a recording from the recording list.
|
||||||
|
*
|
||||||
|
* @param recording - The recording to be deleted.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
deleteRecording(recording: RecordingInfo) {
|
||||||
|
const { recordingList, status, recordingElapsedTime } = this.recordingStatus.getValue();
|
||||||
|
const updatedList = recordingList.filter((item) => item.id !== recording.id);
|
||||||
|
|
||||||
|
if (updatedList.length !== recordingList.length) {
|
||||||
|
this.updateStatus({
|
||||||
|
status,
|
||||||
|
recordingList: updatedList,
|
||||||
|
recordingElapsedTime
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -187,13 +210,12 @@ export class RecordingService {
|
||||||
*/
|
*/
|
||||||
setRecordingList(recordings: RecordingInfo[]) {
|
setRecordingList(recordings: RecordingInfo[]) {
|
||||||
const { status, recordingElapsedTime, error } = this.recordingStatus.getValue();
|
const { status, recordingElapsedTime, error } = this.recordingStatus.getValue();
|
||||||
const statusInfo: RecordingStatusInfo = {
|
this.updateStatus({
|
||||||
status,
|
status,
|
||||||
recordingList: recordings,
|
recordingList: recordings,
|
||||||
recordingElapsedTime,
|
recordingElapsedTime,
|
||||||
error
|
error
|
||||||
};
|
});
|
||||||
this.updateStatus(statusInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -210,23 +232,35 @@ export class RecordingService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private startRecordingTime() {
|
private startRecordingTimer() {
|
||||||
|
if (this.recordingStartTimestamp === null) {
|
||||||
|
this.recordingStartTimestamp = Date.now();
|
||||||
|
}
|
||||||
|
if (this.recordingTimeInterval) {
|
||||||
|
clearInterval(this.recordingTimeInterval);
|
||||||
|
}
|
||||||
|
|
||||||
this.recordingTimeInterval = setInterval(() => {
|
this.recordingTimeInterval = setInterval(() => {
|
||||||
let { recordingElapsedTime, recordingList, status } = this.recordingStatus.getValue();
|
if (!this.recordingStartTimestamp) return;
|
||||||
|
|
||||||
|
let { recordingElapsedTime } = this.recordingStatus.getValue();
|
||||||
if (recordingElapsedTime) {
|
if (recordingElapsedTime) {
|
||||||
recordingElapsedTime.setSeconds(recordingElapsedTime.getSeconds() + 1);
|
// Calculamos con precisión el tiempo transcurrido
|
||||||
recordingElapsedTime = new Date(recordingElapsedTime.getTime());
|
const elapsedSeconds = Math.floor((Date.now() - this.recordingStartTimestamp) / 1000);
|
||||||
const statusInfo: RecordingStatusInfo = {
|
const updatedElapsedTime = new Date(0, 0, 0, 0, 0, 0);
|
||||||
|
updatedElapsedTime.setSeconds(elapsedSeconds);
|
||||||
|
|
||||||
|
const { recordingList, status } = this.recordingStatus.getValue();
|
||||||
|
this.updateStatus({
|
||||||
status,
|
status,
|
||||||
recordingList,
|
recordingList,
|
||||||
recordingElapsedTime
|
recordingElapsedTime: updatedElapsedTime
|
||||||
};
|
});
|
||||||
this.updateStatus(statusInfo);
|
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private stopRecordingTime() {
|
private stopRecordingTimer() {
|
||||||
clearInterval(this.recordingTimeInterval);
|
clearInterval(this.recordingTimeInterval);
|
||||||
const { recordingList, status, error } = this.recordingStatus.getValue();
|
const { recordingList, status, error } = this.recordingStatus.getValue();
|
||||||
const statusInfo: RecordingStatusInfo = {
|
const statusInfo: RecordingStatusInfo = {
|
||||||
|
|
Loading…
Reference in New Issue