Struggling with recording OpenVidu 3.1.0

Hi Carlos,

Regarding the timer tag, as you can see, we have tried implementing it but haven’t achieved positive results yet.

It’s possible that the method we’re using to send the signal only works for remote participants and not for the local participant.
I’m sharing the method here so you can take a look and help us identify any issues:

sendSignalToRemoteParticipants(signaData: any, topic: string, destinationIdentities: string[] = []): void
{
        console.log('sendSignalToRemoteParticipants(', signaData, topic, destinationIdentities, ')');

        const strData = JSON.stringify({ data: signaData });
        const data: Uint8Array = new TextEncoder().encode(strData);
        const options: DataPublishOptions = { reliable: true, destinationIdentities: destinationIdentities, topic: topic };

        this.participantService.publishData(data, options);
}

We are also using this event handler but it accepts only RemoteParticipants or undefined as the participant? parameter.

room.on(RoomEvent.DataReceived, (payload: Uint8Array, participant?: RemoteParticipant, kind?: DataPacket_Kind, topic?: string)

If you could suggest a better method or alternative implementation, it would be very appreciated.

Best regards,
Matteo

I believe you’re trying to send data from the client side, whereas I suggested doing it on the server side

Hi Carlos,

If it is possible, we would like to do it on the client side. Is there the possibility to use a correct method sendData on the client side?
If we could not do it on the client side, we could handle the signal sended by the server side using the livekit openvidu library imported on our angular project, right? Or we could use one of the methods of the openvidu components library?
If it so could you give us an example on how to do it?

Greetings,
Matteo

Hi all,

We would really appreciate a response on this matter, as it has become urgent for our application’s progress.
We cannot understand how to implement a correct method sendData on the client side in order to send the signal.

Thanks for support!
Matteo

Hi Matteo,

To be honest, I’m not entirely sure what you mean by “LiveKit OpenVidu library imported in our Angular project.” Could you please clarify that part?

Here’s my understanding of your situation:

  • You want to detect when a recording starts and stops to display a tag in the UI.
  • You prefer not to send a signal from the backend to the frontend when webhooks are triggered.
  • Instead, you plan to rely on the client-side recordingStatusChanged event to update the UI. This approach is less precise, but it might be sufficient for your needs.

If you leave destinationIdentities undefined, the event should be broadcast to the entire room. You can check the official documentation here.

That said, when sending the event from the client side, you don’t have access to the full information needed to construct the RecordingInfo payload.

For this reason, I recommend once again that you send the event from the server to the client.

Please let me know if I’m missing something.

Hi Carlos,
I think there is a misunderstanding between us in this topic.
I read many times the LiveKit documentation about sending signals to the participants, however even if I leave the destinationIdentities empty or null, my local participant doesn’t receive the data.

I leave here a video where you can clearly see the behaviuor. [VIDEO]
Then, I leave here the piece of code that help me handle the signals events:

// Permette di ottenere i dati della sessione.

onRoomCreated(room: Room): void
{
    console.log('onRoomCreated()');

    // Listener per la registrazione della sessione.

    room.on(RoomEvent.RecordingStatusChanged, async (recordingStatus: boolean) =>
    {
        console.log('Recording status changed: ', recordingStatus);
    });

    // Listener per i signal verso partecipanti remoti.

    room.on(RoomEvent.DataReceived, (payload: Uint8Array, participant?: RemoteParticipant, kind?: DataPacket_Kind, topic?: string) =>
    {
        if(topic == 'signal_example')
        {
            const { data } = JSON.parse(new TextDecoder().decode(payload));
            const participantName = participant?.name || 'Unknown';

            console.log('Topic: ', topic + ', Sender: ', participantName + ', Message: ', data);
        }
    });
}

Then, I leave here the piece of code that allow me send the signal to all participants:

sendSignalToAll()
{
    const strData = JSON.stringify({ data: 'Hey!' });
    const data: Uint8Array = new TextEncoder().encode(strData);
    const options: DataPublishOptions = { reliable: true, topic: 'signal_example' };

    this.participantService.publishData(data, options);
}

I hope this can solve our misunderstanding and help you understand my request.
Thank you again for all your explainations.

Greetings, Matteo.

When sending an event from the client side using room.localParticipant.publishData, the event is delivered to all participants in the room except the local participant (the sender). This behavior is expected.

If you want the event to be received by all participants, including the sender, you should broadcast the event from the server side instead.

Hi Carlos,
I’ve tried to send the signal from the server to the front-end and it worked, however some parameters value are missing.

I leave here the example code of my front-end application:

// Permette di ottenere i dati della sessione.

onRoomCreated(room: Room): void
{
    console.log('onRoomCreated()');

    // Listener per la registrazione della sessione.

    room.on(RoomEvent.RecordingStatusChanged, async (recordingStatus: boolean) =>
    {
        console.log('Recording status changed: ', recordingStatus);
    });

    // Listener per i signal verso partecipanti remoti.

    room.on(RoomEvent.DataReceived, (payload: Uint8Array, participant?: RemoteParticipant, kind?: DataPacket_Kind, topic?: string) =>
    {
        console.log('payload: ', JSON.parse(new TextDecoder().decode(payload)));
        console.log('participant: ', participant);
        console.log('kind: ', kind);
        console.log('topic: ', topic);
    });
}

Then, I leave here the example code of my backend application:

$svc = new RoomServiceClient($sLiveKitAPIURL, $sLiveKitAPIKey, $sLiveKitAPISecret);
$svc -> sendData($aData['eventCode'], json_encode(['data' => $aEgressData]), 1, [], 'recordingStarted');

Here’s the result handled by my front-end application:

Why participant and topic parameters are empty while kind parameter not?
I’ve also checked the sendData() method in the LiveKit PHP library and the parameters are all setted up correctly on my end.

/**
   * Sends data message to participants in the room.
   *
   * @param string $roomName
   *   The name of the room.
   * @param string $data
   *   The payload to send.
   * @param int $kind
   *   The delivery reliability.
   * @param string[] $destinationIdentities
   *   Optional, list of participant identities to receive packet,
   *   leave blank to send the packet to everyone.
   * @param string|null $topic
   *   Optional, topic for the packet.
   *
   * @return \Livekit\SendDataResponse
   *   The SendDataResponse object.
   */
  public function sendData(string $roomName, string $data, int $kind, array $destinationIdentities = [], ?string $topic = NULL): SendDataResponse {
    $videoGrant = new VideoGrant();
    $videoGrant->setRoomName($roomName);
    $videoGrant->setRoomAdmin();
    return $this->rpc->SendData(
      $this->authHeader($videoGrant),
      new SendDataRequest([
        'room' => $roomName,
        'data' => $data,
        'kind' => $kind,
        'destination_identities' => $destinationIdentities,
        'topic' => $topic,
        'nonce' => random_bytes(16),
      ])
    );
  }

Greetings, Matteo.

Hi all,

We would really appreciate a response on this matter, as it has become urgent for our application’s progress. Our project is scheduled to go into production on July 15th, and we need clarification regarding the recording parameters.
Specifically, we are unable to understand why some parameters are empty while others are not. Your assistance in resolving this issue would be greatly appreciated.

Thanks for support!
Matteo

Hi Matteo,

  1. The participant will be undefined when the data packet is sent from the server side — this is expected behavior in LiveKit.
  2. Regarding the missing topic, I recommend debugging your implementation to isolate the issue. You can try sending a hardcoded string as the topic to verify if the problem persists. This will help determine whether the issue lies in how the topic is being set on the server or how it’s being received on the client.

Let me know what you find or if you’d like help reviewing the relevant part of the code.

Hi Carlos,

Regarding the first point, we’re wondering why the participant is only visible on the front-end and not on the server side. Is there a specific reason for this behavior?

As for the second point, you mentioned that we need to send the topic recordingStarted in order for the recording timer to display correctly. We tried this initially, but it didn’t work. We then tested with another string (e.g., "hello"), but it consistently returns undefined.

At this point, we’d like to understand how we can move forward and whether you could verify that none of the parameters are incorrectly set on your end.

Greetings,
Matteo

The reason the participant is only visible on the client side and not from the server side is because, when the server sends a data packet (using the LiveKit server SDK), it doesn’t originate from a specific participant — the server itself is not a participant in the room.

Sure! You need to include the topic when sending signals.

If you’re having issues with the sendData method in PHP, I recommend debugging your code to identify where the problem might be — for example, confirming that the topic is being correctly passed and encoded.

Here’s a working Node.js snippet you can use as a reference:

	async sendData(roomName: string, rawData: Record<string, any>, options: SendDataOptions): Promise<void> {
		try {
			const data: Uint8Array = new TextEncoder().encode(JSON.stringify(rawData));
			await this.roomClient.sendData(roomName, data, DataPacket_Kind.RELIABLE, options);
		} catch (error) {
			this.logger.error(`Error sending data: ${error}`);
			throw internalError(`sending data to LiveKit room '${roomName}'`);
		}
	}

where SendDataOptions is

export type SendDataOptions = {
  /** If set, only deliver to listed participant identities */
  destinationIdentities?: string[];
  destinationSids?: string[];
  topic?: string;
};

Hi Carlos,
sorry but this is taking too long and I need to understand why the library doesn’t send me back the topic information.
As I said in this post Struggling with recording OpenVidu 3.1.0 - #28 by Developer3010 I followed the instruction of the PHP LiveKit Library (that are also what you shared to me in the previous posts) and I shared with you all the information you needed (my front-end code, my back-end code and the method of the LiveKit library).
Do you need something else to help me understand why this isn’t working?

Furthermore, how can I debug a method that isn’t mine? I simply use the sendData() method as you shared with me (Struggling with recording OpenVidu 3.1.0 - #14 by CSantosM) and this method is written in a library that I’ve downloaded from composer, so there are no chances for me to debug it.

Greetings, Matteo.

Matteo are you using the latest PHP library version?

This version added support to topic in sendData method…

Hi Carlos,
I was using the 1.2 version and after the update to the 1.3 the parameters arrived correctly.

Greetings, Matteo.

Hi all,

I have a timer in the frontend that shows the elapsed recording time. It works fine, but I’m facing an issue: when a user loses connection and then rejoins the session while the recording is still ongoing, their local timer resets starting again.

How can I synchronize or restore the correct recording time for users who join (or rejoin) in the middle of an active recording session (now we’re doing it sending a topic on server side which is recordingStarted)?

Is there a recommended way to get the actual recording start time from the server or session, so I can re-calculate the elapsed time on the client side?

Thanks in advance!

Matteo

Of course. Any Egress has the start time as an attribute. You can use your PHP SDK to retrieve the active Egress information from your backend, and send it to your frontend on demand.

You have the protocol definition of the EgressInfo object here at livekit/protocol repository: protocol/protobufs/livekit_egress.proto at 4aaee1f6c6486b91c6f87baa9e73ae8994fcded4 · livekit/protocol · GitHub

Just get the started_at attribute after retrieving the egress using the PHP SDK.

Hi Pablo,
even if I passed the started_at parameter, the result doesn’t change. The timer still continue to be unsyncronized.

This is my back-end code:

Then, this is the result handled in the front-end:

Could you help me please understand what I’m doing wrong?

Greetings, Matteo.

Hi Matteo,

There was a bug related to time synchronization, which has now been fixed.

The payload for the recordingStarted signal should follow the RecordingInfo interface, which includes the startedAt property. Previously, the frontend wasn’t correctly receiving the value of that property, but this issue has now been resolved — it should be available as expected.

To test the fix, please install the latest development version of the package by running:

npm i openvidu-components-angular@dev

Hi all,

We have installed the latest version with the command you provide but nothing change.
image
Our code is the same we shared in the previous message (Struggling with recording OpenVidu 3.1.0 - #38 by Developer3010) but the recording timer is still unsynchronized.
Is there something wrong with the egressData we passed to the signal?

Greetings,
Matteo