Syncing video playback across 2 OBS running on 2 separate computers

markkuo

New Member
Hello, new OBS developer here.

I have a specific need to sync video playback (ffmpeg or VLC source) across 2 OBS instances running on 2 separate computers, under the same local area network. It doesn't have to have strict frame-to-frame sync but both need to play close enough. By close enough, 0.5second isn't good enough. I need something better than "hit play button" at the same time.

My first thought is to implement a simple mechanism like that of mplayer netsync, using UDP sending master OBS video player's timestamp. The master OBS video playback doesn't get changed at all. The slave OBS receives the timestamp and syncs video playback to that timestamp. Audio doesn't matter on slave OBS.

I first experiment with ffmpeg source and do this:
- master: send out mp_media_t's next_pts_ns
- slave: find the difference of next_pts_ns from master's. Add the delta to mp_media_t's next_ns so in the decoding thread mp_media_sleep() will skip the sleep or sleep longer based on the difference

This doesn't work. I then realised there is an additional layer of cache in obs-source.c and async playback on the obs core level where the video frame actually gets rendered. My next thought is I probably need to sync the actual frame rendering timestamp on the obs-source.c, instead of from the VLC or ffmpeg source.

I appreciate any input and how this can be done (or can't be done). Thank you.
 

markkuo

New Member
The problem is the receiver (or the slave on a master/slave setup). How do I adjust to the target timestamp when rendering each frame. Thank you for your input.
 

Suslik V

Active Member
Sorry, I don't get it. I was thinking that you wish to playback video, same as any TV broadcasters do for every consumer.
Probably, you need other tools, not OBS.
 

markkuo

New Member
Sorry I might not have been clear enough. I am using other OBS features that no other tools can replace. Now what I want to do is in one scene I have VLC or ffmpeg source, playing a video. That video is so huge so the video author needs to cut it in half so there are actually 2 video files, of the same length.

Those 2 videos will be played on 2 separate computers (so different OBS instances). A controller (using OBS websocket) will then switch both OBS to the video scene, and start the video playback at the same time. I am building the sync part by modifying OBS source code, so that during the video playback, the 2 OBS instances can perfectly sync, if possible.

Hope that is clear! Thank you.
 

markkuo

New Member
My use case has changed so that it involves just a single computer, running a single instance (of course) of OBS studio, but having 2 VLC video sources in 1 scene. I'd like to sync the video playback on the 2 VLC video sources. It looks like it can easily go out of sync (noticeable after 30-60s of playback).

I will try to do codec level sync and report back. If anyone has any idea please share. Thanks.
 

AaronD

Active Member
I think you need to edit the sources beforehand to become one. Then only play that one live. Or if it was originally one, don't split it.

If you're sending them to different screens, there are devices that take a single large physical signal and split it into smaller ones to send to different displays. Look up "video wall". The computer, then, only sees the one large display, and that's what you produce the content for.
Or, sometimes a video driver allows the PC itself to do that. Same thing, less hardware.

It doesn't have to have strict frame-to-frame sync but both need to play close enough. By close enough, 0.5second isn't good enough. I need something better than "hit play button" at the same time.
Most frame rates are low enough that your requirement pretty much *is* frame-to-frame. They're just barely not noticeable on purpose, which means that it doesn't take much discrepancy at all to become noticeable, if they're side-by-side. And "hit the play button at the same time", done well, can easily hit the same frame or only off by one.

The bigger problem, I'd think, would be clock-drift, which is solved by having a separate master clock that feeds a bunch of slave clocks, and then each of the slave devices runs from the external clock and not its own. No PC that I know of can use an external clock without extensive modification. Thus, two PC's *will* drift relative to each other, and get out of sync, even if you did hit their buttons at *exactly* the same time.
 
Last edited:

markkuo

New Member
Thank you for your response. I agree with you that it's better to just edit the videos to become one. That's what I am doing now, stitching the 2 videos into just 1 video, and played by just one VLC source spanning full canvas.

But my use cases require some reflexibility so we are hoping that the 2 videos can be changed frequently by our user. Hence we plan to use 2 VLC sources to play at the same time so they can update just 1 of the 2 video files when needed, without the need to stitching the videos together each time.

I am thinking since it's 2 VLC sources (or ffmpeg sources), 1 OBS, 1 computer case, that I can probably achieve better results by syncing the internal VLC video pts (or ffmpeg codec pts). But I haven't started anything yet.
 

AaronD

Active Member
What happens if you set your 1 OBS for a big canvas and output to match a big logical display, that is split later into your physical displays, and put 2 VLC sources on it? Or 2 Media sources, or whatever works. Size each to fit *exactly* on its assigned display (not full-canvas: right-click -> Transform -> type your numbers in), and set both of their Properties to reset when not visible, and to play when shown, or whatever those options are called. Right-click the Program window, and put a Full Screen Projector on your big display that splits later.

If you have multiple scenes like that, then you can set up one while another plays, and then switch seamlessly. Haven't tried all of that myself, but it seems like it *should* work. Everything running the same way on the same machine *should* eliminate any relative clock drift, and keep them in sync with each other.
 
Top