OBS Studio

I assume just about everyone who searched for a screen casting software in the last three years has heard of OBS Studio (or formerly just OBS). At this point it is an industry standard for recording and streaming videos. Since the complete rewrite there’s no reason not to use it: it’s free, open-source and cross platform.

A while ago I tried to write a plugin for the original OBS at which I failed tremendously at, for one because of my incompetence but also because it was badly documented and pretty tedious. Recently I got back to that idea of writing a plugin for it but now since it switched to being crossplatform the process changed completely.

Sadly it’s still pretty obscure, which shows in the fact that there’s barely any plugins for OBS Studio. It seems like the setup process is what keeps a lot of people from making a plugin and those who get it to work stop after finding out that there’s no real documentation (Except code comments). After spending about two days on setting OBS Studio up, I got it to work and after some more time spent I finished my plugin.

It adds a new source type to OBS which shows keyboard and mouse input on stream. If you want to check it out you can get it here. But now I’ll talk a little about the setup process.

Working with OBS Studio’s source code

This post is rather long so if you don’t like reading you can watch my video tutorial:

 

The only real documentation is the guide up on github. But even with those instructions some things are a little unclear. For this guide I’ll assume you want to set up a development environment on windows.

So first of the requirements:

  • Visual Studio (2013 or 2015)
  • Qt5
  • cmake
  • Libraries
  • Git (Recommended)

Visual Studio 2017 was just released but I had no luck when trying to use it so I used VS 2013 Community. The following parts will show you how to set up all requirements, except Visual Studio, just google for the installer of the desired version and install it.

Dependencies

Now you should set up a dedicated folder for your development with obs (here refered to as “obs-dev/”) and download the dependencies first (Dependencies for Visual Studio 2013/2015). Unzip them and put them in a sub folder (here refered to as “obs-deps”).

Qt5

It’s not all that obvious as to how to get Qt5, since the guide only mentions folder names like D:\Qt\5.8\msvc2013 or D:\Qt\5.8\msvc2013_64. So first head to the Qt page and download the installer. Then skip the login part and select only these options when installing (These are the required ones, since everyting else just takes up disk space):

Unbenannt.png

Now obviously if you have Visual Studio 2013 you dont need msvc2015 and the other way around. Also if you only want to develop for 64 bit you don’t need 32 bit and vice versa. You can uncheck everything else, except the Qt creator since that ones required.

Note: You can only install Qt to a path that does not contain spaces, in my case

C:\Qt\

Cmake

Cmake is the software OBS uses to configure the environment for developing and it will take care of all the complicated stuff. So just install it, or download a portable version from the offical cmake page.

Git

This is only used to grab the source code and if you want to keep track of your changes. Get it here.

Putting it all together

Now let’s put all these new toys to use: First grab the source code from github via git. Open git bash (by default right click in your obs-dev folder and choose “open git bash here”) then enter this command

git clone --recursive https://github.com/jp9000/obs-studio.git

now you’ll have a sub folder called obs-studio, nice! Though this is the very latest and bleeding edge stuff. That’s cool if you’re planning to just build OBS or contribute to it’s development, but if you want to develop a plugin it’s better to use the latest stable release, so let’s turn back time to the latest stable release. Type:

git tag -l

This will list all past releases of obs studio. At the bottom there should be the latest version (eg. 20.0.1), now let’s load that version by running

git checkout 20.0.1

or if you plan on using git to track your changes

git checkout 20.0.1 -b plugin-dev

The second command will create a new branch with the name “plugin-dev”, this assures that all your future changes will be tracked on a separate branch without touching the original obs code (You obviously can’t acutally change the original code without having the right permissions, but it still helps to keep your local repository tidy).

That’s all we need from git, we now have stable releas of OBS we can base our plugin on.

Configuring Cmake

This step is only needed if you want to develop a plugin for OBS, if you just want to compile it or want to direcetly commit to the obs repository (in pull-requests), you can directly go to “Using Cmake”

Cmake by default only creates project files for OBS and it’s plugins. But our plugin isn’t included since it doesn’t exist yet. Let’s fix that by telling cmake to create an empty project for us. Head into “obs-dev/obs-studio/plugins” and create a new sub folder for your plugin (in this case “test-plugin”). Now inside that folder you need a file called “CmakeLists.txt” and a *.c or *.cpp file with the same name as your plugin. You can keep it empty, but we need something to fill your project for now. The last thing you need is a “data” folder with another folder called “locale”. Inside that you put your language files to translate your plugin (by default only “en_US.ini”.

So this is how your folder structure should look like by now:

  • test-plugin
    • data
      • locale
        • en_US.ini
    • CMakeLists.txt
    • test-plugin.c(pp)

Now we can leave all files empty except the CMakeLists.txt. This needs to contain information for Cmake so it can create the project. You can take a look at other plugins or copy what I have:

project(test-plugin)

if(MSVC)
 set(test-plugin_PLATFORM_DEPS
 w32-pthreads)
endif()

set(test-plugin_SOURCES
 test-plugin.cpp)

add_library(test-plugin MODULE
 ${test-plugin_SOURCES})
target_link_libraries(test-plugin
 libobs
 ${test-plugin_PLATFORM_DEPS})

install_obs_plugin_with_data(test-plugin data)

Just replace all instances of  “test-plugin” with your plugin name. The last thing we need to do is go back to the “plugins” folder and edit the CMakeLists.txt file which is inside that folder. At the bottom of that file you’ll see a bunch of “add_subdirectory(…)” lines. Just add another line with your plugin and save it.

add_subdirectory(test-plugin)

And that is all you need to do to tell CMake about your plugin, now we’ll let CMake take care of the rest.

Using Cmake

Open up the Cmake-gui and then set “Where is the source code:” to “obs-dev/obs-studio” and “Where to build the binaries” to a separate folder where you want to have all Visual Studio projects (it won’t actually put the binaries there), for me the folder is “obs-dev/obs-studio/vs”. Now click configure and select the Visual Studio version you use. You can choose between “Visual Studio <2013/2015>” and “Visual Studio <2013/2015> Win64”. Using 64 bit means your project will build 64 bit binaries and the same for 32 bit.

cmake1.PNG

After it’s done it’ll spit out some errors since it can’t smell where you put the dependencies. You’ll have to set two variables QTDIR and DepsPath. Both of these can be suffixed with “32” or “64” to tell Cmake what bit the dependencies are. So you either just set QTDIR, or if you want both 64 and 32 bit you’ll set QTDIR32 and QTDIR64. For me this is how I set them:

  • QTDIR32: C:/Qt/5.8/msvc2013
  • QTDIR64: C:/Qt/5.8/mscv2013_64
  • DepsPath32: ../obs-dev/obs-deps/win32
  • DepsPath64: ../obs-dev/obs-deps/win64

Note: Cmake uses forward slashes for paths since all Operating systems do that except Windoze.

cmake2.PNG

In this screenshot I only used the 64 bit dependencies, which means I can directly use “DepsPath” and “QTDIR”. If you want 32bit and/or 64bit you’ll need to click “Add entry” and add “DepsPath32” / “DepsPath64” and “QTDIR32” / “QTDIR64”, and set their values accordingly.

Keep in mind that the dependencies are different for VS 2013 and 2015! Now click configure again and after it finishes it’ll let you change some other settings which are unimportant for us so just click configure a third time and there should be no red items in the Cmake list left. After all that you can click Generate, which will create the Visual Studio Solution. When that is done you can click Open Project or directly open the solution.

cmake3.PNG

This is how Cmake should look like after the second configuring process (After you entered “DepsPath” & “QTDIR”).

And that’s it. Give VisualSudio some time since OBS is a huge project and it takes some time to index all the files. You should now be able to click the green play button and the latest version of OBS should run. If you configured CMake to create a project for your plugin you should also see a project with your plugin name in the project explorer.

vs.PNG

So this was all I had to go through to develop a small pugin that probably no one will use. If you compare this essay to the guide up on github you’ll see that it’s missing a couple of things. For experienced developers this process might be self explanatory but for a newbie like me it was quite the nerve wrecking adventure. Maybe this write up will prevent at least one persone from going throught that same process.

Advertisements

fping on windows

I started working on a ping plotter a while ago and back then I still was on linux and was currently getting into C. Now that I’m not on linux anymore I kinda dropped the project for a while. After that pause I’ve finally gone back I decided to ditch C and write it in Python since I’m developing it on windows but want it to work on linux aswell. The ping plotter is supposed to ping an ip over a timespan and then make a graph out of the latency values. For that I’ll use the ping command since that’s the easiest way to get latency values without adiministrative rights. The issue is that the windows ping.exe and the linux ping command return different outputs so formatting them means I have to differenciate between windows and linux.

After some searching I came across fping which is a custom ping program for linux. It’s designed to be used in scripts which digest it’s output. So now the only issue is to compile that for windows. I used cygwin for it since nobody seems to have done it before me. Sadly the build script returns errors when compiling. So here’s how I fixed that:

First get the sourcode from the releases. Now we’ll need to convince cygwin that we have the right headers. Download this header file (made by John Paul Morrison) as icmp.h. Copy it into these folders and replace it with the icmp.h that is in those folders (That one is empty, you can open it if you want):

\usr\include\icmp.h
\usr\include\cygwin\icmp.h

The path to cygwin will usually be C:\cygwin64\ or C:\cygwin\. Now you can run

$ ./configure
$ make

Now you’ll have a fping.exe in the ./src/ folder. Run a command prompt as admin and then run something like

C:\fping\src>fping.exe -s google.com

That should give someting like this

google.com is alive

       1 targets
       1 alive
       0 unreachable
       0 unknown addresses

       0 timeouts (waiting for response)
       1 ICMP Echos sent
       1 ICMP Echo Replies received
       0 other ICMP received

 36.6 ms (min round trip time)
 36.6 ms (avg round trip time)
 36.6 ms (max round trip time)
        0.038 sec (elapsed real time)

Pretty cool, huh? But if you read carefully it needs adminstrative rights on windows and root rights on linux so all of that was kinda wasted… I’ll just use the output of the native ping commands instead but if anyone needs fping on windows here you go. For those whore are to lazy to compile it themselves you can download my compiled binary for windows here (By the way there seems to be an infected version of fping on the web so if you need some confidence, that this one isn’t a virus heres a virustotal scan or scan it yourself). It’s completely unmodified and all credits go to the original authors.

I’ll now go back to getting back into python and formatting ping command outputs. Wohoo.

Wifi issues

This is something that I already dealt with about a year back but it has come again to hunt me. A year back I tried to make use of an old laptop (An IBM T23 to be exact) and install linux on it. The laptop doesn’t have any internal wifi card so I went with an old wifi usb drive. But that thing was already hard to use on windows so getting it to work on linux was a whole different story. First I needed ndiswrapper to get the windows driver to work. But that didn’t do the trick so I went ahead and asked on the Arch linux forums. In the end I dug up a solution which worked for me back then.

A year later I dig up another laptop (An IBM T41 this time) and tried the same procedure. Sadly the thing that did the trick last time wasn’t the whole solution. After some more careful reading of my old thread I put together what is needed to get a wifi pci card or a wifi usb drive to work on an old ibm with linux:

First you need ndiswrapper. For Arch it’ll look like this:

$ sudo pacman -S ndiswrapper

If you have issues running ndiswrapper later you might need the linux headers:

$ sudo pacman -S linux-header

Next up we need to install the driver:

$ sudo nidswrapper -i <driver>.inf

The *.inf file is usually distributed with the driver, sometimes it’s inside the *.exe which means you’ll need to extract it using cabextract.

Now you want to plug in the device of which you just installed the driver and run

$ ndiswrapper -l 

This will list all installed drivers and wether or not the device is present. If it says so the driver is correct and the device is recognized. Now with most devices the last thing you want to do is load ndiswrapper on startup using

$ sudo ndiswrapper -ma

And since this is your first time using it you’ll have to load it manually once:

$ sudo modprobe nidswrapper

Now the device should be ready to use and you can connect to your network using a network mananger or wpa_supplicant. But for me this wasn’t all that was needed. What I need to do is disable ipv6 by editing /etc/sysctl.d/40-ipv6.conf

net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.<wifi device>.disable_ipv6=1

You can find the device name by typing ip link and for me it was the last listed device. The next thing to do is add these two lines to /etc/dhcpcd.conf

noipv6rs
noipv6
# Also comment out the line that says something like 'ipv4all'

Now this command has to be executed on every startup:

$ sudo dhcpcd <wifi device> --nohook mtu
# Once again get the wifi device with ip link

Now finally we’ll generate a wpa_supplicant config using

# wpa_passphrase <Networkname> <network password> /home/<username>/wifi.conf

You can get your exact Network name by scanning for networks over:

$ sudo pacman -S wifi-menu
$ sudo wifi-menu

Don’t use wifi-menu to connect (It’ll probably not work, but you can try).

Finally we can use the config to connect via wpa_supplicant:

sudo wpa_supplicant -D wext -B -i <wifi device> -c /home/<username>/wifi.conf

To automate the connection you can follow the Arch wiki or create a service.

And that’s it, wasn’t all that hard, right? 😛

Livestreamer without commandline

Update: Livestreamer has been discontinued and has been replaced by StreamLink. So everytime I mention livestreamer just imagine I’m talking about StreamLink. It’s a fork of it and works exactly the same.

Now that my adventures on linux are over for a while I realized that some things are a lot harder on windows than on linux. For example: I use livestreamer (Now Stream Link) to watch livestreams in VLC.

VLC playing a livesteam over livestreamer

Originally because I wanted to avoid the Flash player and now that almost everyone has switched to HTML5 I use it only for convenience. On linux I started livestreamer like this:

$ livestreamer high & disown

Which allowed me to close the command line afterwards. Sadly windows doesn’t work that way so I always have to leave the cmd window open. But when something’s annoying enough I’ll fix it at some point and with this problem it’s possible over a *.vbs script.

This is the script I’m using (pastebin.com):

Dim streamer
Dim quality
Dim link

streamingSite = “twitch.tv”       ‘ The Site you want to grab the stream from
default       = “gamesdonequick”  ‘ The stream that is shown by default in the text box
defaultq      = “high”              ‘ The default quality

streamer = InputBox(“Enter livestream channel”, “livestreamer”, default)
quality  = InputBox(“Enter quality”, “livestreamer”, “high”)

link = “livestreamer ” & streamingSite & “/” & streamer & ” ” & quality & ”  –http-header Client-ID=jzkbprff40iqj646a697cyrvl0zt2m6″

CreateObject(“Wscript.Shell”).Run link,0,True
Set objShell = Nothing

Just save it as a *.vbs file and change the three variables to fit your needs and when launching it you should see this:

After clicking ok on the second dialog it’ll take some time, and if Livestreamer is installed correctly and finds a player (eg. VLC) you should see the player opening with the livestream and no command line. The last thing I did was make a shortcut of it and give it a nice icon.

MPD Query

So I mentioned in another post that I use mpd and ncmpcpp to listen to music. The positive thing about this is that I can just close ncmpcpp when I don’t need it anymore and the music will continue playing, since mpd is responsible for the sound which is running completely in the background. Now sadly I have no indicator about what song is playing right now.

So I looked if anybody made a patch for dwm to display the current song, but everything I found didn’t really work for me. And I didn’t want a bash script to be running in the background. So I found a few people suggesting to make a simple C program to query the current song.

Now this is easier said than done, since I have no idea how to use mpd and C. The first thing I did was download the source code of mpd and copied the include directory into my project folder. So now I can write a program utilizing code from mpd. Now for the tricky part: Getting my program to connect to mpd and get the song name and some other information. I had some example code which showed how to connect and get the play time of the current song, so that helped a little bit, but getting the song name doesn’t work the same way.

For experienced people this task probably would be a thing of ten minutes but I not only had to deal with how mpd worked I also had to figure out how C works. And most time that was me writing like three lines of code, compiling it and finding out it compiled fine but crashed when running. So here’s what I have done so far:

Created a Makefile where the include directory (which containes the headers of mpd) is:

Makefile

VERSION = 3.02
CC      = /usr/bin/gcc

mpdq: mpdq.c
    $(CC) -o mpdq -lmpdclient mpdq.c

So this way compiling is just the command ‘make’. Next up is writing the actual code which started by me finding out how the main method looks in C and then moving onto actually fiddling with mpd. To work with mpd I needed these two headers:

#include <mpd/client.h>
#include <mpd/stats.h>

When those are included and the compiler doesn’t complain about not finding them you should be able to access the necessary methods to connect and query information from mpd:

struct mpd_connection  *connection = mpd_connection_new(NULL, 0, 0);

This will open a connection to the local mpd and return the pointer to the connection if it succeeded. The three arguments are only needed if the connection is to another computer. After that we want to get the current song and from that we can read most Song tags:

// Get current song as a struct
struct song = mpd_run_current_song(connection);
// Read name and artist
char *song_name   = (char *) mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
char *artist_name = (char *) mpd_song_get_tag(song, MPD_TAG_ARTIST, 0);

And that is technically everything important to read information from mpd. The only other things I did were putting this in a loop, adding a command to make it appear in the dwm bar, differentiating between paused/playing and  cleaning up when closing. That’s all I have done up until now. I’ll see if I can get some controls like pause/play into the dwm bar but for now this’ll suffice.

DMEDYKJ

Here‘s the source code and here‘s a binary build. Just give it the run flag with chmod a+x and when running it should display the current song in the top left corner (Provided you use dwm and a song is playing in mpd :P).

Rocket League on Linux

So recently Rocket League got a linux version, which is currently in beta. But since I’m currently using Linux more than windows I thought I’d give it a try.

On Windows my controller just works when plugged in and is directly configured correctly. On linux, sadly it needs a little more work. Nothing surprising. So what I did was look around and found out that the default driver for controllers and joysticks, xpad, does not support Xbox controllers and any controllers that mimic them. Mine is some cheap Xbox 360 knockoff but it works just like an original one and I never had any issues on Windows.

So for linux, you’ll need a custom driver called xboxdrv. For the arch linux users, you can get it on the AUR here. I suggest you use an extention for pacman to support the AUR like yaourt, which makes installing software from the AUR a whole lot easier.

So when I got my hands on xboxdrv I started it as root (which is required) just to find out that Rocket League does not like it. Loading the driver works perfectly and programs like PPSSPP or other games work just fine. But in Rocket League I had several problems like constanly going in reverse without pressing any button, constantly looking up and other strange mismappings for the buttons. So after a lot of googling I stumbled upon someone else who happened to have issues with Rocket League and his controller as well. He posted his config for xboxdrv, which I promptly tried out and reduced to the important part. And with that config it worked perfectly without any issues and the exact same button mappings as on windows.

So here’s what I did:

Write this to a config file e.g. /home/username/xboxdrv.conf

[xboxdrv]
 silent = true
 mimic-xpad = true

and then run xboxdrv with the config:

$ sudo xboxdrv --detach-kernel-driver --config /home/username/xboxdrv.conf

And that’s it you can set it up so the driver runs in the background as a daemon but I’m waay to lazy to do that since I only need it for Rocket League 😛

Arch linux and dwm

So this is not the first time that I use arch and dwm, but after getting a new video card and cpu I took a break from using it and went back to windows.

Now that I’ve used windows for a while I decided to take a look at arch again. Sadly, like last time I used it, I had a few annoying issues when installing it. But those were mostly faults on my side.

Arch linux is a really customizable linux distribution which allows you to modify it from the ground up to fit your needs. That also means that installing process takes place in the console. No fancy GUIs. But the basic installation is a pretty straight forward process if you follow the guide.

What you get when booting the installation medium

Sounds like a doable thing, right? Well when I did this the first time the only issues I had were with dualbooting. Which ended up toasting my bootmanager. But that can be fixed with a windows installation disk. So booting the installation medium this time just got me a black screen. Fantastic. Later I found out that that is because I have a “fairly” new nvidia card which need the extra kernel parameter nomodeset to even get to the console.

So after all that and making sure that grub played nice with my windows partition I ended up installing xserver and other things I needed. That was when arch asks you which package you want for libgl. Theres a vesa package (I think that’s the opensource one) and three nvidia packages. Great. Now on the wiki it tells you which you need for your video card but reading the wiki is for loosers so I used the next best package. After installing the nouveau driver, which is the opensource driver for nvidia cards everything looked good. Until I rebootet and got a blackscreen instead of dwm. Now that’s not the first time I had that happend, I once had that on ubuntu as well when I installed the video card driver.

So the first thing where I don’ goofed is in the .xinitrc file. That file is executed when you start the xserver (which is responsible for the fancy nancy graphical stuffs). In there you tell it what window manager to start. But before starting my window manager I ran another command which prevented my window manager from starting. Soo yeah, that explained the blackscreen. After fixing that I found my desktop to be in a very low resolution, but at least I saw a desktop.

I spend about an hour trying to fix this problem by intalling the nvidia drivers from the repositories and the offical website switching between blackscreens and a low res desktop and ended up reinstalling arch completely.

This time I directly installed the proprietary drivers and tadaa, everything worked out fine. I still need to configure a few things like auto mountin usb drives and mounting my windows partition. But all in all I’m happy to get a break from windows from time to time and use linux.

My current setup (Open programs are caja and surf)

For dwm I applied the following patches systray and pertag so I have a sytem tray aswell as seperate modes for all virtual desktops.

That’s it. I also installed mpd and ncmpcpp, just because it looks cool 😀