-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Synchronized playback over a network #1272
Comments
Porting this back to mpv shouldn't be too hard. But I don't like the way mplayer integrates this (it looks like it blocks the player on network to achieve sync), so it should be done differently. The branch udp_sync contains an earlier attempt. |
I believe this is the only thing blocking the adoption of mvp over mplayer for a client project that relies heavily on mplayers udp sync stuff. I wish I had the time & knowledge to help here because I can honestly say mpv > * as a media player. I now use it over VLC. |
The most annoying thing is actually that it'd require raw network programming, which is painful/unportable if it should work on windows. |
I'm using the udp sync feature in mplayer right now for a video wall, but I'm running multiple slaves on a single machine (rather than across a network). The challenge with this is that the UDP port is blocked by the first slave, thus subsequent slaves are not able to listen. I've got a hacky work-around to this, but it would be nice to also have a solution that uses a non-network approach for sending timestamps between instances on a single machine. Just a thought. |
Do you have a specific mechanism in mind? |
👍 |
👍 Would leveraging an external dependency like http://zeromq.org make it easier? |
👍 This would really be awesome. |
Hey guys, any progress on this feature please? |
Nobody is working on it. It could now be implemented without mpv changes via one of the following mechanisms:
|
@wm4 cool, so any network synchronized protocol and wrapper around mpv should suffice? Also I've found this, but theres no documentation. https://github.com/derlaft/synco |
@smarek You could also look at http://syncplay.pl/ I don't know if it's accurate enough to use as a video wall (like MPlayer's UDP-sync apparently was,) but it definitely can sync multiple mpv instances over a network. |
I've recently did just what Smarek offered - used --input-ipc-server mode to synchronize mpv and osmcplayer from kodi on raspberry pi. Supports play/pause detection. I used it mostly to show video from raspberry pi but take audio from a better audio card on a separate computer. Not perfect but I find it watchable most of the time. |
I've been trying to do this through libmpv and have had some success, however it isn't quite frame perfect. I'm using a loop similar to this:
` Basically I subscribe to changes of the "time-pos" property, then set the time-pos of every slave player instance. This gets really close to what I want, but sometimes doubles a frame or skips a single frame and I'll end up off by one for a bit before returning to the correct timing. Is there a better method that I could use here? The time-pos property appears to update once per frame, so it is a bit course for this. |
A better method would be adjusting playback speed for small deviations. Also "time-pos" is somewhat asynchronously reported, so it can definitely happen that it's off by a frame or more. |
Ok, I can try that and see how it works out. I saw in issue #5592 that there may be a delay in adjusting the playback speed. I could probably work around that, but is that normal behavior? I'm also working on code to sync the playback time across the network accounting for network delay and some amount of jitter. I'm writing all this as a separate executable that calls libmpv, but I could try to merge it into mpv itself. Would that be something you'd be interested in merging, or should I keep it separate? Thanks for the help! |
Hi, Do you have any suggestions or pointers into the right direction before I start? I have read that the blocking socket read behaviour on the slave side is undesired. Does anyone have an idea what a better solution might look like? However, I believe this is an implementation detail that can be changed at any time without affecting the network packet format or user experience. I've got a couple of days time at my disposal and a video wall with multiple slaves to test the whole thing. Edit: Now I could be satisfied, but I see a problem when the slave gets slightly out of sync. Mplayer has a pretty elegant solution to this using the blocking udp read. It is not as stupid as it might look first. The video playback loop essentially ceases to use it's own timing and relies on the operating system to block the thread until a UDP packet arrives. This ensures that the slave does not play the video faster then the master. It also has a very low latency, lower than propagating events via threads. The question now is, how to implement that in mpv. I fear it'll be a lot more complex and messy when not using a blocking socket. Edit2: Edit3: |
I built mpv with the network sync stuff, but I am clueless on how to use it properly. Any help there will be greatly appreciated. Also, anyone done any further work since last year? mplayer is great and all, but when utilizing Intel graphics & libvdpau-va-gl anything other than h264 is a no go. |
2nixternal: The request_id could be arbitrary. { "command": ["set_property", "speed", 1.0]} to set speed Commands should be sent through a socket. Run mpv like this: for more see section JSON IPC from https://mpv.io/manual/master/ |
Regular NTP can be pretty darn good on a wired network. A really standard, interoperable way could be to just use the system time. It's probably never going to be worse than your ping time, and WiFi almost always let's a few 2ms or so packets through. Daemons like Chrony have this stuff all figured out, why reinvent? Even Windows can apparently do 1ms sync? Using a --wallclock-start=TIMESTAMP, you could tell MPV that you want to play synced to wallclock, with the start of the video at exactly that time. If the command needs time to process and it can't hit the time you specified, or it's in the future, you skip or delay as needed so that the current position is always what it would be if you started exact then. With 1 second of video locked to 1 second of real time, everything is perfect as long as they get the same time. You can even start them at different times. No communication is actually needed here, you could just have GPS. Network issues will not cause stuttering as long as they are brief enough that the clocks stat synced. This would be troublesome manually, but from there it's easy to add a tiny bit of automation with 2 really simple packets. The first one gets a --sync-group=name argument, and the second one gets a --sync-join argument. The second sends a multicast packet asking for the group master's start time, putting the name in the UDP. Once it gets that, no communication is needed. |
There is a big need for this and osc frame search. the omxplayer-sync approach is quite good, |
To anyone considering giving this a go: don't forget about buffering & latencies introduced by the underlying layers. I'm not familiar w/ video renderers, but all audio backends (e.g. PulseAudio, Pipewire, Core Audio, etc) will introduce some latency, and even a tiny amount of drift can lead to problems. For example, a drift of just a 10ms between 2 speakers playing concurrently will produce a noticeable "murky" effect. It's easy to reproduce on one's system. Just pick some track, downmix it to mono, upmix it back to stereo, then add a delay to one channel. And we haven't even mentioned phase issues. |
I suspect most users used |
Yeah, I have machines in the field that have been running for years with mplayer -udp-master & -udp-slave, all running sound. Only time we have ever noticed any sort of drift is poorly made videos. When we keyint=1 so every frame is keyed, the only way you would detect any drift is with a picture or record a video & go frame-by-frame. |
@nixternal that's interesting. Do you do anything to control audio backend latency — i.e. anything that would ensure that the audio backend on each machine running mpv is within the same tight range? Come to think of it, using identical machines running same OS would probably qualify. @Frenzie i wasn't really commenting on UDP latency. My point was only aimed at the latency that audio backends introduce — e.g. PulseAudio can easily introduce >100ms latency since low latency was never one of its design goals. |
@guillaumekh we don't do anything at all in regards to audio latency. Our machines are built upon the Intel NUC so there is a chance they are all the same, but usually just similar on the rental side. All running some LTS version of Ubuntu. mPlayer isn't bad, but with Intel you can't do h.265 or anything bigger than 4k. The mplayer-vaapi project is long gone & dead, and the whole vdpau-vaapi stuff is a mess. We are now using Pulse as our backend, but used Alsa prior to using 18.04 iirc. |
Thanks for taking the time to share this. I'm still mulling this over but maybe the factor here is that in most environments, sound will take many different paths from speakers to listeners, each with its own small delay, which would help hiding sync drift between sources. Anyway, I came to this problem with some knowledge of how this specific subject of audio sync is often handled these days in professional audio systems (e.g. concert venues, malls, hotels, stadiums, etc). See Dante/AES67/SMPTE2110, all of which use PTP to ensure precise sync. It's quite interesting to hear you're getting away without all this (expensive) stuff :) |
Yeah, we looked at all of the Dante stuff as well, and it still confuses me about as much as DMX does, but they UDP sync with mplayer is so good, when you keyint=1 every frame. If you don't, yeah there "could" be a little noticeable drift.
We run this quick little script on every video & they have been flawless. Like I tell my clients, garbage in, garbage out which has been the case. |
Description source: http://www.mplayerhq.hu/DOCS/HTML/en/networksync.html
Mentioned on issue #898.
Also on #252 (comment).
The text was updated successfully, but these errors were encountered: