This brief script came about from numerous requests to play multiple videos in sync with each other from a single machine. The videos were to have different content but would be of the same duration. Achieving this on macOS has proved to be a little tricky to say the least. It is possible to run multiple instance of VLC so that videos can be played concurrently from the same machine.
Be aware that this method does not enforce any syncing, so it is possible for the videos to fall out of sync, especially if the are not exactly the same frame count and encoding.
If precision is required you may want to invest in a ocuple of Rapsberry Pis and check out the following
- omxplayer-sync further multi-video sync
- and omxplayer-sync-2
- for real-time streaming, check here
- Piwall if you wish to spread a video across displays, or sync the same video over multiple displays
- Node OMXPlayer
- Video Tryptic
- VDMX
You can play multiple videos just by using the VLC CLI tool, which should live at
/Applications/VLC.app/Contents/MacOS/VLC
You can run multiple instances of VLC concurrently
/Applications/VLC.app/Contents/MacOS/VLC $FILE1 & \
/Applications/VLC.app/Contents/MacOS/VLC $FILE2
This will run two instances but you can easily daisy chain this by adding more lines with the &
operator
i.e.
/Applications/VLC.app/Contents/MacOS/VLC $FILE1 & \
/Applications/VLC.app/Contents/MacOS/VLC $FILE2 & \
/Applications/VLC.app/Contents/MacOS/VLC $FILE3 & \
/Applications/VLC.app/Contents/MacOS/VLC $FILE4 & \
/Applications/VLC.app/Contents/MacOS/VLC $FILE5 & \
/Applications/VLC.app/Contents/MacOS/VLC $FILE6
you can repeat the video with the -R
flag
e.g.
/Applications/VLC.app/Contents/MacOS/VLC -R $FILE1 & \
/Applications/VLC.app/Contents/MacOS/VLC -R $FILE2
This requires that you manually set each instance to full screen in a seperate display, which becomes tiresome after a while. So what about playing in fullscreen from the get go?
To play on different displays with VLC CLI macOS you have to the flag
--macosx-vdev=<screenID>
Where screen ID is some integer identifying the screen. Unhelpfully, this is not a sequential 1
, 2
, 3
, ...
but rather an 8 digit decimal number whose value is elusive to find.
There is the odd forum post on the matter, but if you're not sure what you're looking for they are of little help.
Cutting to the chase, the screen ID can be found in the vlcrc
file located at
/Users/USERNMAME/Library/Preferences/org.videolan.vlc/vlcrc
Find / search for --macosx-vdev
, switch the display in VLC preferences and check this file again.
This is a little tedious, especially if you intend on using different displays. So I opted to automate it a little with Swift
Below is a CLI tool which you can compile in Xcode.
- Create an Xcode Command Line Tool Project
- Choose language Swift
- Paste the below code
- build
- copy app in Product folder to the folder with your videos
Assuming the project was named vlc-multi-screen
the CLI tool takes the form
./vlc-multi-screen $file1 $file2 ... $filexx
Where the number of files is equal to the number of displays
//
// Play multiple instances of VLC player, fullscreen across multiple screens
//
//------------------------------------------------------------------------------
import Foundation
import Cocoa
//------------------------------------------------------------------------------
if (CommandLine.argc - 1) != NSScreen.screens.count
{
print("Number of files does not match number screens\n")
exit(0);
}
//------------------------------------------------------------------------------
var screen_id = [String]()
for screen in NSScreen.screens
{
screen_id.append(String(screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")]! as! Int)) ;
}
print(screen_id)
//------------------------------------------------------------------------------
// get files
var files = [String]()
for i in 1...Int(CommandLine.argc - 1)
{
files.append(CommandLine.arguments[i])
}
//------------------------------------------------------------------------------
func shell(_ args: String...) -> Void
{
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
}
//------------------------------------------------------------------------------
// Run VLC
let vlc_path = "/Applications/VLC.app/Contents/MacOS/VLC"
for file in files
{
let display = "--macosx-vdev=" + screen_id.popLast()!
shell(vlc_path, "-f", display, file);
}