My OBS setup for recording screencasts

published on February 21, 2018.

Last year I started recording my contributions to open source. I wasn’t really regular, so today I published only the 9th episode: OSS Contribution 9.

Anyway, now I’m at the point where I am happy with the overall quality of the recording, both with the video and the audio and I want to write down the current setup so that I can recreate it in the future if I need to.

I’m using a Sennheiser GSP 300 headset and the microphone that comes with it. A really great product, I love it.

PulseAudio is responsible for the audio in my Fedora system. In the “Input Devices” settings of PulseAudio, I have set the “loudness” of the microphone to 25% or -35.94dB. I got there after a lot of trial and error.

As for the recording software, I was first using Zoom, which is a video conferencing and screen sharing tool. Start a meeting with myself, share screen, record. Buuut… I was never really happy with the audio.

I tried out Open Broadcaster Software, or OBS, last week. Again, after a lot of trial and error, I think I have the perfect settings given the hardware that I’m using. I picked it up from Swizec, he’s using it for his live coding sessions I believe.

“Settings > Output”: Output mode: simple, video bitrate: 2500, encode: software (x264), audio bitrate: 160, recording quality: indistinguishable quality, recording format: mp4. “Settings > Audio”: Sample rate: 44.1khz, the rest is all default. “Settings > Video”: Base resolution: 1920x1080, output resolution 1920x1080, the rest is default.

The most improvement came from setting filters on the microphone — “Mic/Aux > gear icon > Filters”. The first filter I added is “Noise Suppression” with a value of -17. The second filter is “Noise Gate” with a “Close Threshold” of -44, “Open Threshold” of -42, “Attack Time” 25ms, “Hold Time” 200ms, and “Release Time” 150ms. These last three might be the defaults, I’m not sure. I did play around with them.

Now, I said I’m happy with the audio, but I know it can be much better. One, I need to speak louder, and two, if these screencast become a more regular thing then I’ll invest in a better microphone. Until then, this will do.

Happy hackin’!

Tags: obs, screencasts, recording, about.
Categories: Software, Blablabla.

Details matter

published on February 19, 2018.

Last week on Thursday the lovely people from Zagreb PHP had me over for a talk. I presented my new talk called “All aboard the Service Bus”. I gave this talk once before at the PHP Srbija meetup in January. I’ve reused the slides, made some minor adjustments based on the feedback I received in Belgrade, and of course updated the footer.

The version from Belgrade had “Robert Basic - PHP Srbija #29” and the version from Zagreb had “Robert Basic - ZGPHP #78” in the footer.

The talk went well. I was a bit tired, as I drove 5 hours, my mind was racing a bit more than what I’d like, but all in all, I was/am very happy with how the talk went.

When I was done with the talk in Zagreb, people came up to me, said it was a nice talk, gave me some feedback, and then asked what’s up with the “29”, where did I get that number? I was confused. What? “29”? I don’t have any numbers on my slides, let alone a specific number like “29”.

“ZGPHP 29, in the footer”, said Luka, “I’ve spent a lot of time thinking what does it mean.”

I somehow managed to update only one part of the footer — changed the user group, didn’t change the meetup number. I apologized, explained, and shrugged it of. It’s just a number in the footer after all, has nothing to do with the actual talk.

On the drive back home, my mind kept going over it again and again.

It might be just a number, a small detail, but a detail that was incorrect, a detail that Luka noticed, a detail that made him think about that number 29 instead of paying his full attention at the actual talk.

Details matter.

Tags: about, talks, meetups, slides, presentation.
Categories: Blablabla.

Docker nginx host not found in upstream error

published on January 30, 2018.

I’ve been toying around with Docker for the past couple of days, mostly to learn more about it, to understand it better. I just didn’t bother with it until now.

I started from scratch. Installing Docker, configuring it (I really don’t appreciate it filling my root partition with images), and, well, using it. I sort of figured out the docker command line interface, I get the difference between images and containers, I know how to write a Dockerfile, and when all the commands and options and flags start get confusing I know where to look in the help for help.

Happy with the progress I made, it was time to start connecting different containers so that they can talk to each other. Starting with a single container with nginx in it, and another container with php-fpm in it. Using their official images even.

To keep my sanity intact, as much as it is possible with software these days, I heeded Vranac’s advice and installed docker-compose for that.

No cheating, so I wrote my own docker-compose.yml file using just the documentation:

version: '3'
services:

    php:
        image: php:7.2-fpm
        expose:
            - "9000"
        volumes:
            - ./app:/app

    nginx:
        image: nginx:stable
        ports:
            - "8080:80"
        volumes:
            - ./site.conf:/etc/nginx/conf.d/default.conf
            - ./app:/app
        depends_on:
            - php

And now let’s build it and bring up the containers:

$ docker-compose build
$ docker-compose up

Aaaaaaand… It dies with an error like:

nginx: [emerg] host not found in upstream "php" in /etc/nginx/conf.d/default.conf:15

Blergh. I guess I missed something from the documentation. Fast-forward 2 hours, dozens of google searches and articles, countless rewrites of the docker-compose.yml file, and zero luck. Whatever I did, same error: “host not found in upstream”.

Then I finally remembered. What is the one thing that always causes me grief when trying to work with a web server? That’s right: SELinux!

Turn off selinux, restart docker, build && up, and it works. Sonofa. Works even with the very first version of docker-compose.yml I wrote.

OK, turning off selinux can’t be the solution, so I searched more… And no one, ever, recommends, or even mentions, that selinux might be the problem. I’ve installed the Docker SELinux package (it’s container-selinux on my Fedora 26). It should be working!

Another hour later, more searches and articles, I end up at the beginning, at the “Get Docker CE for Fedora” documentation page. Docker CE? What the fresh hell is this?

Well, it’s the docker version I should’ve installed in the first place.

Fedora’s repos have docker version 1.13.something. Docker-CE is at 17.12.something.

Remove old docker, re-enable selinux, install new docker, everything works just fine, and run the following:

sudo ausearch -c 'iptables' --raw | audit2allow -M my-iptables
sudo semodule -X 300 -i my-iptables.pp

I have no idea what that does, but it was required to make it work.

sigh

Happy hackin’!

Mockery partial mocks

published on January 28, 2018.

In dealing with legacy code I often come across some class that extends a big base abstract class, and the methods of that class call methods on that big base abstract class that do an awful lot of things. I myself have written such classes and methods in the past. Live and learn.

One of the biggest problems with this kind of code is that it is pretty hard to test. The methods from the base class can return other objects, have side effects, do HTTP calls…

A typical example of this would be a base model class that has a getDb() method:

AbstractModel.php

<?php

abstract class AbstractModel
{
    protected $db = null;

    protected function getDb()
    {
        if ($this->db == null) {
            $db = Config::get('dbname');
            $user = Config::get('dbuser');
            $pass = Config::get('dbpass');
            $this->db = new PDO('mysql:host=localhost;dbname='.$db, $user, $pass);
        }
        return $this->db;
    }
}

which can be called in child classes to get access to the database connection:

ArticleModel.php

<?php

class ArticleModel extends AbstractModel
{
    public function listArticles()
    {
        $db = $this->getDb();
        $stmt = $db->query('SELECT * FROM articles');

        return $stmt->fetchAll();
    }
}

If we want to write unit tests for this listArticles() method, the best option would probably be to refactor the models so that the database connection can be injected either through the constructor, or with a setter method.

In case refactoring is not an option for whatever reason, what we can do is to create a partial mock of the ArticleModel using Mockery and then mock (well, stub to be more precise) out only the getDb() method that will always return a mocked version of the PDO class:

tests/ArticleModelTest.php

<?php

use Mockery\Adapter\Phpunit;

class ArticleModelTest extends MockeryTestCase
{
    public function testListArticlesReturnsAnEmptyArrayWhenTheTableIsEmpty()
    {
        $stmtMock = \Mockery::mock('\PDOStatement');
        $stmtMock->shouldReceive('fetchAll')
            ->andReturn([]);
        $pdoMock = \Mockery::mock('\PDO');
        $pdoMock->shouldReceive('query')
            ->andReturn($stmtMock);

        // Create a partial mock of ArticleModel
        $articleModel = \Mockery::mock('ArticleModel')->makePartial();

        // Stub the getDb method on the ArticleModel
        $articleModel->shouldReceive('getDb')
            ->andReturn($pdoMock);

        // List all the articles
        $result = $articleModel->listArticles();
        $expected = [];

        $this->assertSame($expected, $result);
    }
}

When we tell Mockery to make a partial mock of a class, any method on that partially mocked class that has expectations set up will be mocked, but calls to other methods Mockery will pass through the real class. In other words, even though the ArticleModel is a partial mock, anytime we call the listArticles() method Mockery will pass that call to the original method, and only the calls to the getDb() method are being mocked.

Using partial mocks should probably be an option of a last resort and we should always aim to refactor code to be easier for testing, but there are cases when they can really help us in testing legacy code.

Happy hackin’!

Build and run Golang projects in VS Code

published on January 24, 2018.

I’ve been using VS Code for my Golang development needs for a few months now. Minor kinks here and there, nothing serious, and the development experience gets better with every update. I have also tried out IntelliJ Idea as the editor, and one feature that I’m missing in Code from Idea is the build-run-reload process. I thought to myself, that’s such a basic feature, it should be possible to have that.

And it is! VS Code Tasks to the rescue!

These tasks allow us to run different kind of tools and, well, tasks inside VS Code.

Go to Tasks -> Configure Default Build Task and then select the “Create tasks.json file from template” in the little pop-up window, and after that select the “Others” option. This tasks.json file will live inside the .vscode directory.

For my overcomplicated d20 roller, which is my first website built with Golang, I have the following content for the tasks:

.vscode/tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build and run",
            "type": "shell",
            "command": "go build && ./d20",
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

What this one task does is that it runs go build to build the project and then runs the generated executable, which for this project is d20.

I guess providing a standardized name to go build with the -o flag this could be made more portable so that the command part reads something like go build -o proj && ./proj, but I’m ok with this for now.

And now just type Ctrl+Shift+b and Code will execute this “Build and run” task for us! Hooray! The terminal window in Code will pop-up saying something like:

> Executing task: go build && ./d20 <

By going to http://localhost:8080 I can see that my little website is up and running. Cool.

But if we want to restart this taks, running Ctrl+Shift+b again won’t work and Code will complain that the “Task is already active blablabla…”.

Looking at the Tasks menu, we can see that there’s a “Restart running task…” menu entry. Clicking that, it pops up a window with a list of running tasks. In this case there’s only one, our “Build and run” task. Clicking through the menu every time would be boring, so let’s add a keyboard shortcut for it.

Go to File -> Preferences -> Keyboard shortcuts (or just hit Ctrl+k Ctrl+s), search for “Restart running task” keybinding, and set it to whatever you like. I’ve set it to Ctrl+Alt+r.

Finally, the flow is Ctrl+Shift+b to start the taks for the very first time, code-code-code, Ctrl+Alt+r to re-build. Sweet. Now the only annoying bit is that I have to pick out that one running task from the list of running tasks when restarting, but I can live with that. For now.

Happy hackin’!

Robert Basic

Robert Basic

Software engineer, consultant, open source contributor.

Let's work together!

If you require outsourcing or consulting help on your projects, I'm available!

Robert Basic © 2008 — 2018
Get the feed