willprice / python-omxplayer-wrapper

:tv: Control OMXPlayer, the Raspberry Pi media player, from Python
http://python-omxplayer-wrapper.readthedocs.io
GNU Lesser General Public License v3.0
253 stars 72 forks source link

How to sync two videos on separated dbus on a RPi4 #212

Open SandroMiccoli opened 3 years ago

SandroMiccoli commented 3 years ago

Issue Report

Description

I'm upgrading a video controller system I've developed to be able to play two different videos for each HDMI output of a RaspberryPi4 (issue #194 helped with that). My issue now is getting these two videos to play in sync. Ideally synced at the exact same frame.

Looking at the docs I found a play_sync() function but not sure how to make one process to be synced with the other.

Problem reproduction

I had to increase my GPU memory on the RPi to 256MB to be able to play two FHD (1920x1080) for each monitor output (thanks to this).

This is how I'm starting the omxplayer process for each video output:

from omxplayer.player import OMXPlayer
player0 = OMXPlayer('videos/video0.mp4', dbus_name='org.mpris.MediaPlayer2.omxplayer1', args=['--no-osd','--no-keys','-b','--loop','--display=2','-o','local'])
player1 = OMXPlayer('videos/video1.mp4', dbus_name='org.mpris.MediaPlayer2.omxplayer2', args=['--no-osd','--no-keys','-b','--loop','--display=7',])

And when I pause/play the video, they also react in different moments. Parts of that code:

if msg.topic == "pause":
        player0.play_pause()
        player1.play_pause()

Should I use a python library like multiprocessing to run both processes in parallel or are there some settings for omxplayer that could take care of this?

Environment details

Software Version
python-omxplayer-wrapper (pip show omxplayer-wrapper) 0.3.3
python-dbus (dpkg -s python-dbus) 1.2.8-3
python (python --version) 2.7.16
omxplayer (omxplayer --version) f543a0d
szvsw commented 3 years ago

@SandroMiccoli I do not know the answer, but if I were you I would start by seeing how long it takes those calls to the pause function to happen. If the first one always takes 300ms to complete, then that indicates you will need to do some sort of parallel control rather than using the same thread.

szvsw commented 3 years ago

@SandroMiccoli also, play_sync() is just a synchronous version of the play() funcition, i.e. if you call it your code will not proceed to the next line until the video is done playing. It is not referring to any sort of sync between different players.

baronlanteigne commented 3 years ago

I have the same issue. Is there any way to spread a single video across 2 screens on a Pi4 or sync the playback of 2 files in 2 screens?

Akwariom commented 3 years ago

I am using a workaround for this, maybe not the cleanest but it works fine. Use the video on screen 1 as a "Master" and the screen 2 as a slave , and adjust slightly the playing rate of the slave according to the master's position. Something like : pos1=videoplayer1.position() pos2=videoplayer2.position() offset =abs(pos1-pos2).

if(offset>1): #more than 1 second offset, direct jump to correct position videoplayer2.set_position(pos1)

else : #small offset, adjust player 2 rate desiredRate=(pos1-pos2)*0.9+1.0 videoplayer2.set_rate(desiredRate)

I use the same logic to sync as many rPis using omxplayer-wrapper as needed on a network (tried with 8 screens so far), communicating with the OSC protocol

Hoping this might help

baronlanteigne commented 3 years ago

@Akwariom I love it. This is a good idea. I didn't know the python wrapper offered that much control. As much as I want to give it a try, I might just stick to two pi3 and omxplayer-sync since I already have an img configured with it.