OpenLP and OBS Integration
Below (at the bottom of this webpage) are two downloads that fully integrate OBS with OpenLP. This allows you to run OpenLP and OBS as separate applications, and use the OpenLP Controller within OBS, as well as lyrics integration using web page overlays. There is also auto-switching of scenes and audio based on whether OpenLP is showing lyrics or showing slides or showing bible verses. There is an automatic countdown based on a fixed time and also overlays for logos.
There is even extra logic to automatically change the Scene to the camera view if OpenLP is blanked or showing the background theme.
They are based on older, more stable versions of OpenLP and OBS.
Installation instructions
To get this going, follow these steps:
Download OBSPortable.zip and OpenLP.zip (see very bottom of this page).
Unzip both files into two separate folders.
Run OpenLPPortable.exe first and wait for 10 seconds.
Run OBSPortable.exe.
You now have full overlays and automatic scene switching controlled by OpenLP.
No installation is required - these are fully portable files that can run even from a USB stick.
WARNINGS
In OBS, never delete the "Untitled" scenes or Profiles. This will reset OBS!!
Do NOT update OBS, as the newer versions of OBS have different webextensions that are not compatible.
Do NOT use "localhost" as this causes OpenLP to run very slowly. Instead use 127.0.0.1 in the URLs for the Web Source and Custom Dock.
Usage Notes
If you want to use BlackMagic ATEM mini ATEM Software Control integration, then see here: ATEM Global Hotkeys
If you would like to run OpenLP on a different computer, then modify the IP address for the Custom Browser Dock, and the Lyrics Source:
OPENLP Stage Code
Here is the code for stage.js. It is based on the sample code from the OpenLP forum https://forums.openlp.org/discussion/5336/tutorial-how-to-control-obs-via-openlp-custom-stage-view/ but switches automatically between scenes by detecting what OpenLP is displaying. There are two modes, manual and auto:
Manual Mode
If the OBS current scene does not have "auto" in the scene title, then ignore any commands from OpenLP. This feature allows you to decouple OBS from OpenLP so you can use OpenLP at the start and end without affecting the live stream.
For instance, this service run sheet will allow you to start a pre-roll video, then switch to the autoCamera at the start. From this point onwards, OpenLP will control OBS scene switching.
Then at the end, play the post-roll.
So when the pre-roll and post-roll videos are running in OBS, you can use OpenLP to display anything you want without fear of affecting the livestream.
2. Auto modes
If OpenLP is not displaying anything then OBS will switch to autoCamera.
If OpenLP is showing song words / bible / notes then OBS will switch to the autoLyrics.
If OpenLP is showing a presentation / video / image then OBS will switch to autoMirror.
If OpenLP is showing an item with the title "scenechange:xxxx" (or in the notes for the item) then it will force OBS to change to that scene.
/******************************************************************************
* OpenLP - Open Source Lyrics Projection *
* --------------------------------------------------------------------------- *
* Copyright (c) 2008-2017 OpenLP Developers *
* --------------------------------------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation; version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., 59 *
* Temple Place, Suite 330, Boston, MA 02111-1307 USA *
******************************************************************************/
window.OpenLP = {
loadService: function (event) {
$.getJSON(
"/api/service/list", // To see all use http:/127.0.0.1:4316/api/service/list
function (data, status) {
for (idx in data.results.items) {
idx = parseInt(idx, 10);
if (data.results.items[idx]["selected"]) {
// inserted for OBS control, I want to be able to read out the information
OpenLP.currentTitle = data.results.items[idx]["title"];
OpenLP.currentNotes = data.results.items[idx]["notes"];
OpenLP.currentPlugin = data.results.items[idx]["plugin"];
// see CSS file
$("#currentslide").attr("data-plugin", OpenLP.currentPlugin);
break;
}
}
OpenLP.updateSlide();
}
);
},
loadSlides: function (event) {
$.getJSON(
"/api/controller/live/text",
function (data, status) {
OpenLP.currentSlides = data.results.slides;
OpenLP.currentSlide = 0;
$.each(data.results.slides, function(idx, slide) {
if (slide["selected"])
OpenLP.currentSlide = idx;
})
OpenLP.loadService();
}
);
},
updateSlide: function() {
// Show the current slide on top. Any trailing slides for the same verse
// are shown too underneath in grey.
// Then leave a blank line between following verses
var slide = OpenLP.currentSlides[OpenLP.currentSlide];
var text = "";
// use title if available
if (slide["title"]) {
text = slide["title"];
} else {
text = slide["text"];
}
// use thumbnail if available
if (slide["img"]) {
text += "<br /><img src='" + slide["img"].replace("/thumbnails/", "/thumbnails320x240/") + "'><br />";
}
// use slide_notes if available
if (slide["slide_notes"]) {
text += '<br />' + slide["slide_notes"];
}
// for OBS, I like replacing new lines by forward slashes
text = text.replace(/\n/g, "<br>");
// text = text.replace(/\n/g, " ◇ ");
$("#currentslide").html(text);
OpenLP.obsRemote();
},
pollServer: function () {
$.getJSON(
"/api/poll", // To see all use http:/127.0.0.1:4316/api/poll
function (data, status) {
if (OpenLP.currentItem != data.results.item ||
OpenLP.currentService != data.results.service) {
OpenLP.currentItem = data.results.item;
OpenLP.currentService = data.results.service;
OpenLP.loadSlides();
// also triggers loadService(), which triggers updateSlide()
}
else if (OpenLP.currentSlide != data.results.slide) {
OpenLP.currentSlide = parseInt(data.results.slide, 10);
OpenLP.updateSlide();
}
//inserted for being able to control OBS by display style
if(OpenLP.currentlyShowing != "blank" && data.results.blank) {
OpenLP.currentlyShowing = "blank";
OpenLP.updateSlide();
}
else if(OpenLP.currentlyShowing != "theme" && data.results.theme) {
OpenLP.currentlyShowing = "theme";
OpenLP.updateSlide();
}
else if(OpenLP.currentlyShowing != "display" && data.results.display) {
OpenLP.currentlyShowing = "display";
OpenLP.updateSlide();
}
else if(OpenLP.currentlyShowing != "slides" &&
!data.results.blank &&
!data.results.theme &&
!data.results.display) {
OpenLP.currentlyShowing = "slides";
OpenLP.updateSlide();
}
}
);
},
obsRemote: function () {
/*
A list of all the information that could be useful to remote control OBS:
pollServer() evaluates /api/poll, provides
- OpenLP.currentlyShowing: blank|theme|display|slides
loadService() evaluates /api/poll, provides
- OpenLP.currentPlugin
- OpenLP.currentTitle
loadSlides() evaluates /api/controller/live/text, provides
- OpenLP.currentSlides[OpenLP.currentSlide]["text"]
- OpenLP.currentSlides[OpenLP.currentSlide]["html"]
- OpenLP.currentSlides[OpenLP.currentSlide]["tag"]
obs-websocket-js documentation at:
https://github.com/haganbmj/obs-websocket-js
obs-websocket controls can be found at:
https://github.com/Palakis/obs-websocket/blob/4.x-current/docs/generated/protocol.md
*/
OpenLP.obsHandler = new OBSWebSocket();
OpenLP.obsHandler.connect({address: 'localhost:4444', password: ''}).then(() => {
// Override scenes with scenechange
// Example 1a: use an item with the title "scenechange:altar" to switch to OBS scene "altar"
if(preg = /scenechange:(.+)/i.exec(OpenLP.currentTitle)) {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': preg[1]});
}
// Example 1b: put "scenechange:altar" into the notes of an item
else if(preg = /scenechange:(.+)/i.exec(OpenLP.currentNotes)) {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': preg[1]});
}
// Automatic scene changes only if the scene starts with "auto", otherwise ignore
else {
OpenLP.obsHandler.send('GetCurrentScene').then(data => {
console.log(data['name'].substring(0,4) === 'auto');
// Check if it is in auto scene
if (data['name'].substring(0,4) === 'auto') {
// If OpenLP is blank, then switch to "autoCamera"
if(OpenLP.currentlyShowing == 'blank' ) {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoCamera'});
}
// If OpenLP is theme, then switch to "autoCamera"
else if(OpenLP.currentlyShowing == 'theme' ) {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoCamera'});
}
// If OpenLP is hidden (i.e. display) then switch to "autoMirror"
else if(OpenLP.currentlyShowing == 'display' ) {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoMirror'});
}
// If OpenLP is showing a song, then change scene to "autoLyrics"
else if(OpenLP.currentPlugin == 'songs') {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoLyrics'});
}
// If OpenLP is showing custom text slides, then switch to "autoLyrics"
else if(OpenLP.currentPlugin == 'custom') {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoLyrics'});
}
// If OpenLP is showing images, then switch to "autoMirror"
else if(OpenLP.currentPlugin == 'images') {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoMirror'});
}
// If OpenLP is showing media, then switch to "autoMirror"
else if(OpenLP.currentPlugin == 'media') {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoMirror'});
}
// If OpenLP is showing presentations, then switch to "autoMirror"
else if(OpenLP.currentPlugin == 'presentations') {
OpenLP.obsHandler.send('SetCurrentScene', {'scene-name': 'autoMirror'});
}
}
});
// Example 2: toggle visibility of OBS scene item "lyrics",
// depending on if the slide your showing is a song or not
// OpenLP.obsHandler.send('SetSceneItemProperties', {'item': 'lyrics', 'visible': (OpenLP.currentPlugin == "songs")});
}
});
}
}
$.ajaxSetup({ cache: false });
setInterval("OpenLP.pollServer();", 50);
OpenLP.pollServer();
OBS configuration SETUP
The following configuration is already part of the portable downloads below, but are included for reference.
OpenLP Web Source:
http://127.0.01:4316/stage/obs
Browser Dock:
http://127.0.01:4316/
Here is an older video showing an example of a previous version of this integration, showing how this is set up in OBS.
Downloads
OpenLP version: 2.4.6
OBS version: 27.2.4
OBS Plugins included:
OBS Websocket 4.9.1: Required for OpenLP to control OBS.
Advanced Scene Switcher 1.17.7: Required for OBS to control ATEM Mini.
Scene Collection Manager: Save scenes for easy recall.
Source Doc 0.3.2: Preview camera source in a docked window.
OBS Face Tracker 0.7.0: Autozoom and track speaker (optional).
OBS Multi RTMP 0.2.8.0: Stream to multiple destinations (optional).
DVD Screensaver (June 2022): Test source.
Droidcam OBS (May 2022): Integrate wireless android phones.
HTML Countdown timer: Fixed timer overlay - see OMedia folder for example configurations.