Segvik
Segvik3mo ago

Play a video in a Room synchronize for all the clients

Hi everyone, I’m developing a virtual meeting room using Unity and Normcore, and I’ve encountered a problem that I haven’t been able to solve: I can’t get a video to play synchronously across different clients connected to the virtual room. I’ve tried several solutions but haven’t had any success. I’ve also referred to this guide (https://normcore.io/documentation/guides/recipes/timers-and-synchronized-playback) but still need assistance. Any help or suggestions would be greatly appreciated. Thanks in advance!
Timers + Synchronized Playback | Normcore Documenation
A common need in Normcore is to synchronize a timeline across all clients for music playback or animation playback. A naive approach would be to choose a main client and have it send updates to all clients to update their timelines. This uses a lot of bandwidth, it can result in choppy playback for the other clients, and playback isn't guarantee...
7 Replies
kapa.ai
kapa.ai3mo ago
Hi @Segvik. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the information provided in the knowledge sources, Normcore does not currently support video streaming directly. However, it does provide a way to synchronize a timeline across all clients for music playback or animation playback. This is done using a synchronized clock that matches the room server's clock exactly with no added latency. The room time is available via the realtime.room.time property. Here's an example of how to use it to create a synchronized stopwatch:
using Normal.Realtime;
using Normal.Realtime.Serialization;

[RealtimeModel]
public class StopwatchModel {
[RealtimeProperty(1, true)] private double _startTime;
}

using Normal.Realtime;

public class Stopwatch : RealtimeComponent<StopwatchModel> {
public float time {
get {
// Return 0 if we're not connected to the room yet.
if (model == null) return 0.0f;

// Make sure the stopwatch is running
if (model.startTime == 0.0) return 0.0f;

// Calculate how much time has passed
return (float)(realtime.room.time - model.startTime);
}
}

public void StartStopwatch() {
model.startTime = realtime.room.time;
}
}
using Normal.Realtime;
using Normal.Realtime.Serialization;

[RealtimeModel]
public class StopwatchModel {
[RealtimeProperty(1, true)] private double _startTime;
}

using Normal.Realtime;

public class Stopwatch : RealtimeComponent<StopwatchModel> {
public float time {
get {
// Return 0 if we're not connected to the room yet.
if (model == null) return 0.0f;

// Make sure the stopwatch is running
if (model.startTime == 0.0) return 0.0f;

// Calculate how much time has passed
return (float)(realtime.room.time - model.startTime);
}
}

public void StartStopwatch() {
model.startTime = realtime.room.time;
}
}
(Source: Timers + Synchronized Playback (https://normcore.io/documentation/guides/recipes/timers-and-synchronized-playback)) You could potentially use this synchronized clock to control the playback of a video across all clients. However, this would require each client to have a copy of the video file and start playing it at the same time based on the synchronized clock. For video streaming, Normcore's new MediaStream API is now available in private preview for Normcore Private customers. If you would like to use video streaming in your Normcore Private app, you should get in touch with your account manager for more information. (Source: Media streams (https://normcore.io/documentation/room/room#media-streams)) Please note that this is a workaround and might not work perfectly for all use cases. It's recommended to reach out to the Normcore team for more specific guidance on this issue. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@141651651571351553> kapa.ai is still learning and improving, please let us know how it did by reacting below
maxweisel
maxweisel3mo ago
what issues are you running into?
Segvik
Segvik3mo ago
Hi @Max, I tried different things but with this code i went far but still not working. It stopped the video on first frame. I try to play the video activating a Remote Control on the scene for all the clients.
NormalMark
NormalMark2mo ago
I don't see any issues with the network portion of the code. I suspect the OnValidate function though. It runs in Play mode when the component is loaded and will replace any older material. I assume a video render texture is assigned to the material? If so OnValidate will clear it. There can be a desync in the playAtStart = true case since it's not transferred to the model as far as I can tell. Generally if there's non-networked state that can be modified before OnRealtimeModelReplaced you'll want to copy that state over to the newly assigned model if it's fresh (model.isFreshModel). I'll try to find an example. There's also a quirk in the Unity video player API. Calling VideoPlayer.Play() and then querying VideoPlayer.isPlaying right away can actually return false in most cases (https://docs.unity3d.com/ScriptReference/Video.VideoPlayer-isPlaying.html). It's safer to keep track of the play/stop video player state in a separate variable for situations like UpdateModel().
NormalMark
NormalMark2mo ago
RealtimeComponent | Normcore Documenation
RealtimeComponent subclasses are the most common way to synchronize data in your application. A RealtimeComponent subclass script is responsible for keeping a specific part of your scene in sync. The most common built-in component is RealtimeTransform, which synchronizes the transform of a GameObject.