Mikameel
Mikameel6d ago

Syncing video from asset files .mp4

This is for testing purposes of the documentation BOT. Please give me a tutorial on how I can sync the playback of video. I want all users to be able to start, stop and pause the video. I'm using unity videoplayer. it's an mp4 file. I'm building for quest.
5 Replies
kapa.ai
kapa.ai6d ago
Hi @Mikameel. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To synchronize video playback across multiple users in a Normcore project for Quest using Unity's VideoPlayer component, we can utilize Normcore's synchronized clock feature. Here's a tutorial on how to achieve this: 1. First, ensure you have Normcore set up in your Unity project and have a VideoPlayer component added to a GameObject in your scene. 2. Create a new script called SyncedVideoPlayer.cs and attach it to the same GameObject as your VideoPlayer. 3. Use the following code as a starting point for your SyncedVideoPlayer.cs:
using UnityEngine;
using UnityEngine.Video;
using Normal.Realtime;

public class SyncedVideoPlayer : RealtimeComponent<SyncedVideoPlayerModel>
{
[SerializeField] private VideoPlayer videoPlayer;

private double _startTime;
private bool _isPlaying;

public override void OnRealtimeModelReplaced(SyncedVideoPlayerModel previousModel, SyncedVideoPlayerModel currentModel)
{
if (previousModel != null)
{
previousModel.startTimeDidChange -= StartTimeDidChange;
previousModel.isPlayingDidChange -= IsPlayingDidChange;
}

if (currentModel != null)
{
if (currentModel.isFreshModel)
{
currentModel.startTime = 0;
currentModel.isPlaying = false;
}

currentModel.startTimeDidChange += StartTimeDidChange;
currentModel.isPlayingDidChange += IsPlayingDidChange;

UpdateVideoPlayerState();
}
}

private void StartTimeDidChange(SyncedVideoPlayerModel model, double value)
{
UpdateVideoPlayerState();
}

private void IsPlayingDidChange(SyncedVideoPlayerModel model, bool value)
{
UpdateVideoPlayerState();
}
private void UpdateVideoPlayerState()
{
if (model.isPlaying)
{
double currentTime = (realtime.room.time - model.startTime) % videoPlayer.clip.length;
videoPlayer.time = currentTime;
videoPlayer.Play();
}
else
{
videoPlayer.Pause();
}
}

public void TogglePlayPause()
{
model.isPlaying = !model.isPlaying;
if (model.isPlaying)
{
model.startTime = realtime.room.time - videoPlayer.time;
}
}
}
using UnityEngine;
using UnityEngine.Video;
using Normal.Realtime;

public class SyncedVideoPlayer : RealtimeComponent<SyncedVideoPlayerModel>
{
[SerializeField] private VideoPlayer videoPlayer;

private double _startTime;
private bool _isPlaying;

public override void OnRealtimeModelReplaced(SyncedVideoPlayerModel previousModel, SyncedVideoPlayerModel currentModel)
{
if (previousModel != null)
{
previousModel.startTimeDidChange -= StartTimeDidChange;
previousModel.isPlayingDidChange -= IsPlayingDidChange;
}

if (currentModel != null)
{
if (currentModel.isFreshModel)
{
currentModel.startTime = 0;
currentModel.isPlaying = false;
}

currentModel.startTimeDidChange += StartTimeDidChange;
currentModel.isPlayingDidChange += IsPlayingDidChange;

UpdateVideoPlayerState();
}
}

private void StartTimeDidChange(SyncedVideoPlayerModel model, double value)
{
UpdateVideoPlayerState();
}

private void IsPlayingDidChange(SyncedVideoPlayerModel model, bool value)
{
UpdateVideoPlayerState();
}
private void UpdateVideoPlayerState()
{
if (model.isPlaying)
{
double currentTime = (realtime.room.time - model.startTime) % videoPlayer.clip.length;
videoPlayer.time = currentTime;
videoPlayer.Play();
}
else
{
videoPlayer.Pause();
}
}

public void TogglePlayPause()
{
model.isPlaying = !model.isPlaying;
if (model.isPlaying)
{
model.startTime = realtime.room.time - videoPlayer.time;
}
}
}
4. Create a model script called SyncedVideoPlayerModel.cs:
using Normal.Realtime;
using Normal.Realtime.Serialization;

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

[RealtimeProperty(2, true)]
private bool _isPlaying;
}
using Normal.Realtime;
using Normal.Realtime.Serialization;

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

[RealtimeProperty(2, true)]
private bool _isPlaying;
}
5. After creating these scripts, make sure to compile them so that Normcore can generate the necessary model code. 6. In your scene, ensure you have a Realtime component set up with your App Key, and that your VideoPlayer component is properly configured with your .mp4 video file. 7. To control the video playback, you can call the TogglePlayPause() method on your SyncedVideoPlayer component. You might want to set up UI buttons or input controls to trigger this method. This setup uses Normcore's synchronized room time to keep the video in sync across all clients. When a user plays or pauses the video, it will update for all connected users. Remember that for Quest builds, you'll need to ensure you've followed the Meta Platform Prerequisites and have properly set up your Meta app and Unity project for Quest development. Please note that this is a basic implementation and may need further refinement depending on your specific requirements, such as seeking to specific times or handling network latency. Normcore Documentation provides more detailed information on synchronizing custom data and using Normcore's features, which you might find helpful for further customization of this video synchronization system. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai6d ago
<@365574199844274177> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mikameel
MikameelOP6d ago
@Normcore Assistant I get this error on the public override void OnRealtimeModelReplaced , on line 14: Override method 'void VideoNetworking. SyncedVideoPlayer. OnRealtimeModelReplaced(SyncedVideoPlayerModel, SyncedVideoPlayerModel)' cannot change access @Normcore Assistant I get this error on the public override void OnRealtimeModelReplaced , on line 14: Override method 'void VideoNetworking. SyncedVideoPlayer. OnRealtimeModelReplaced(SyncedVideoPlayerModel, SyncedVideoPlayerModel)' cannot change access
kapa.ai
kapa.ai6d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion in my previous response. The error you're encountering is related to the access modifier of the OnRealtimeModelReplaced method. Let's correct this issue. The OnRealtimeModelReplaced method should be protected instead of public. This is because it's overriding a protected method from the base class. Here's the corrected version of the method signature:
protected override void OnRealtimeModelReplaced(SyncedVideoPlayerModel previousModel, SyncedVideoPlayerModel currentModel)
protected override void OnRealtimeModelReplaced(SyncedVideoPlayerModel previousModel, SyncedVideoPlayerModel currentModel)
This change should resolve the error you're seeing. The rest of the method's content can remain the same. This correction is based on the standard implementation of RealtimeComponents in Normcore. As mentioned in the RealtimeComponent documentation, the OnRealtimeModelReplaced method is a protected method that you override to handle model changes. If you're still encountering issues after making this change, please let me know, and I'd be happy to help further. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai6d ago
<@365574199844274177> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?