How to record screencasts with webcam overlay on Linux

How to record screencasts with webcam overlay on Linux

If you want to record your Linux screen with a nice borderless overlay of your webcam’s image, you may use this SimpleScreenRecorder and MPlayer.

Screenshot from 2016-05-07 18:30:20.png

You can check out the official SimpleScreenRecorder website at “Download” section on how to install it. Considering you are using Ubuntu 14.04, as I am, it is quite straightforward to do:

sudo add-apt-repository ppa:maarten-baert/simplescreenrecorder
sudo apt-get update
sudo apt-get install simplescreenrecorder

The software is, as the name says, simple to use. Just open it up and it will guide you through the recording options.

It does not have an option to show your webcam overlay, so this is the part where MPlayer comes into play.

To install MPlayer on Ubuntu 14.04, simply install it from standard repositories:

sudo apt-get install mplayer

Or, you can check MPlayer’s official website on other ways to obtain it.

To add a 320×240 borderless window streaming video from your webcam at the bottom right corner of a 1920×1080 screen, that’s the command you are looking for:

mplayer -ontop -noborder \
  -geometry 320x240+1600+840 \
  -tv driver=v4l2:width=320:height=240:device=/dev/video0 tv://

This command tells MPlayer to create a window streaming from /dev/video0 that stays on top of others, has no border, has size of 320x240px, is offset by 1600px horizontally and by 840px vertically.

You may tweak those parameters depending on your screen resolution, the desired window size and the webcam resolution.

But, don’t start making those calculations. I’ve created a simple shell script that can extract your screen resolution and correctly position the webcam overlay at the bottom right corner. Check it out on GitHub:

If you want to record multiple workspaces, you will need to tell your window manager to keep the MPlayer window visible on all workspaces, otherwise it will only appear on one workspace. I’ve found two ways to do it on Ubuntu 14.04 using Unity window manager.

  1. After opening up the webcam overlay window, focus on it (click with your mouse on it), press Alt+Space to open the context menu and click on “Always on Visible Workspace”.
  2. Install “compizconfig-settings-manager” and “compiz-plugins”, open up compiz settings manager, enable “Windows Rules” plugin and set “Sticky” rule to “class=MPlayer”. This will make every MPlayer window to be visible on all workspaces by default.Screenshot from 2016-05-07 18:24:03.png

Now go record your own screencast and share your ideas with the world!


I’ve made some casual mobile games so you can have a good time even when you are not doing great stuff like recording screencasts. Check it out at


Talking to self

Talking to self

This was posted on my portuguese blog back on 2009. Check it out.

– What is reality?
– Everything around you.
– Is it absolute?
– It depends on your senses.
– What do I sense as real?
– Images, sounds, emotions, feelings and any other experience you may have.
– If I lack a sense, do I lose reality?
– Your reality changes.
– Can I lose the notion of reality?
– The reality of others, yes.
– And of mine?
– No.
– Why not?
– Isn’t it obvious? Whatever you experience will be your reality.

– What if I don’t like reality?
– You may flee.
– I don’t want to.
– Because running away can be more painful.
– So I’m stuck to reality?
– You still can flee.
– I’m not a coward!
– In the reality of who?

– How can I run from everything that surrounds me?
– Only you sense what surrounds you.
– I can’t stop sensing!
– And is it a bad thing?
– This makes me suffer.
– Who generates the pain?
– I don’t know…
– Is there anyone else that controls your reality?

– So, happiness only depends on me?
– Yeah.
– But without the notion of reality they will call me crazy!
– That’s the reality of others.
– I suffer with it.
– Again generating suffering?

– So a crazy man can be happy?
– Isn’t him happier than you?

– Why do I feel like this?
– Because you interpret your current state as bad.
– Why?
– Because they told you so.
– Told what?
– That being below others is a bad thing.

– What?
– You interpret as unhappiness the fact that you have less than the others.
– I’m not selfish!
– Really?
– Yes!!!
– And why did you feel sad when you knew that your friends were dating?
– Because… I wanted a date to.
– Bingo.
– But…
– Would you be happy if you had a date before them?
– I don’t know…
– If you were the first to buy a car…
– Stop…
– Or the first one to open up a business…
– Stop!
– Ok.

– I don’t know what to do…
– Oh, gosh. Didn’t you get what I said?
– I’m afraid.
– Of what?
– Of others.


Isn’t it nice to remember good stuff about yourself? I make some casual games in the hope that they can bring you some good memories. You can know more about my work at Thanks for reading!


Life is hard, and it’s your fault

Life is hard, and it’s your fault

You realize that you are on a bad spot and guess that more money, health, passion and friends could make your life better.

So, you decide to seek after those things. After all, you won’t be defeated by life. You know what I mean. You work very hard for it and, against the odds, you end up winning a big prize from a mix of luck and effort.

Happiness is just next door, you think. Then, your body starts shivering in fear. Is that it? Is this what lies after the rainbow? What would you do with your life now? What if you fail in this new position of your life? All those paranoid voices are inside of your head and you feel helpless. You can’t seem to get rid of it.

As a last resort, you give up. All the effort you put on it and the hope you had about it is gone. It’s gone for good.

You learned a lot of stuff during this process. It seems to be a good thing, but this haunts you now. It’s like winning ten million dollars and losing nine. You still got your million dollars, but the feeling of the lost nine is massive.

Everything you do now seems to remind you about your lost nine million dollars and you get yourself locked on thoughts about how your life would be if you didn’t lose it.

How do you get out of this?

Well, you need to realize that life still carries on. There is nothing holding you back. You may have lost nine million dollars. But who cares? A lot of people tries really hard and will never have the opportunity to feel this. Not that you should feel better because others are in a worse position than you, but you should notice that you are, in fact, on a really privileged position. You need to be proud of your current realizations.

Life is just a single experience. It’s a single shot that goes really fast. Don’t measure your realizations by the eyes of other people.

There is a powerful TEDx talk that I’ve seen recently: “How to know your life purpose in five minutes” by Adam Leipzig. You can watch a video of the talk at the end of this post.

I will spoil a bit of the content, please watch the talk to get the full idea and drop a nice gratitude message to the author.

Adam Leipzig lists five questions that you should answer to know your life purpose:

  1. Who are you?
  2. What do you do?
  3. To whom do you do it?
  4. What those people want and need?
  5. How do they change as a result of your work?

The first question is really straightforward, it’s just your name, so you are self-aware. The next one is a bit harder, as you need to nail down what you really do and love doing – your passion. The following three questions is about other people and not yourself. That’s interesting: to know your life purpose, you should know more about others than about yourself.

Who are the ones impacted by your work? What they want? How do they change or transform as a result of what you do?

After answering those five questions, when someone asks you what do you do, just use the answer of the fifth question. That’s your personal pitch, it is what you really do. You change and transform other peoples life and experience. That’s your life purpose. It’s your little dent in the universe.

It’s just five questions, but they are tricky to answer, at least for me. There are multiple answers for it. Looks like my life is full of purposes I didn’t realize before:

Dear Adam,

I’m Thiago Borghezan Negri.

I make my family feel loved and supported by giving them my attention and working to provide for them.

I make people’s life better, easier and lighter to carry by making casual games for them to play.

I make people remember good stuff by reviving their memories through experiences they have had with their loved ones.

I present people with good ideas by writing posts like this.

I save people’s time by providing them code and help through this blog and other sites.

I receive some inflamed opinions now and then about my posts, ideas and works, but they won’t bring me down. I do what I do because I believe in it. I may have lost one big pot, but this is life. It is hard, and I’m a big part of making it feel hard. It’s also intriguing and satisfying to discover more about it and about myself!

Here is the talk from Adam Leipzig:


You can get to know more about my work by checking out Drop your comment and I will answer it. Thanks for reading!

Word Hunter

Word Hunter

I’m pleased to announce that Word Hunter has been released to iOS, Android and Windows Phone.🙂

It’s written 100% in web technologies and packaged via Apache Cordova.

Go take a look, I hope you have some fun with it:

The game is made by @danielsalvagni, Gabriel Biz and me (@evohunz).

Tip of the day. We did it while reading Getting Real and Rework. Incredibly how these books affected how we dealt with the development of this project. Changed my mind for sure.

By the way, my personal highscore is 935 points.

Active Directory Authentication in Java

Doing Active Directory authentication in Java can be a nightmare. Documentation is scarse and Java APIs are usually counter-intuitive.

I’ve spent a good time to get it right (or what I guess is right), and I hope that this code sample can help others. Just use it, code is under WTFPL license.

Summary to validate if a user is in a group:

  1. Java requires the user full DN to authenticate;
  2. Authenticate to LDAP using a master user;
  3. Search user DN;
  4. Reauthenticate using user DN;
  5. Fetch all groups of user;
  6. Check if the required group is in it.
package com.tnegri.sample;

import java.util.*;

import javax.naming.*;

public class ActiveDirectoryFacade {

    private static final MASTER_USER_DN = "CN=masteruser,OU=Admins,OU=Users,DC=tnegri,DC=com";
    private static final MASTER_PASSWORD = "m4sterP4ssw0rd";
    private final String ldapUrl;
    private final String searchBase;

     * @param ldapUrl LDAP URL, e.g. "ldap://"
     * @param searchBase Base for doing user search, e.g. "OU=Users,DC=tnegri,DC=com"
    public ActiveDirectoryFacade(String ldapUrl, String searchBase) {
        this.ldapUrl = ldapUrl;
        this.searchBase = searchBase;

    public boolean hasGroup(String username, String password, String groupObjectName) throws NamingException {
        List<String> allGroups = getAllGroups(username, password);
        return allGroups.contains(groupObjectName);

    private List<String> getAllGroups(String username, String password) throws NamingException {
        List<String> result = new ArrayList<>();

        String attributeToLookup = "memberOf";

         * 1. Authenticate using master user.
        DirContext ctx = authenticate();

         * 2. Searches by "sAMAccountName" to recover the full DN of the username trying to login.
        SearchControls searchControls = new SearchControls();
        searchControls.setReturningAttributes(new String[] { "distinguishedName" });
        NamingEnumeration<SearchResult> searchResults =, String.format("(sAMAccountName=%s)", username), searchControls);
        if (!searchResults.hasMore()) {
             * If can't resolve DN, the user doesn't exists.
            throw new NamingException();
        SearchResult searchResult =;
        Attributes attributes = searchResult.getAttributes();
        Attribute attribute = attributes.get("distinguishedName");
        String userObject = (String) attribute.get();

         * 3. Authenticates to LDAP with the user, will throw if password is wrong.
        ctx = authenticate(userObject, password);

         * 4. Fetch all groups of user.
        attributes = ctx.getAttributes(userObject, new String[] { attributeToLookup });

        NamingEnumeration<? extends Attribute> allAttributes = attributes.getAll();
        while (allAttributes.hasMoreElements()) {
            attribute = allAttributes.nextElement();
            int size = attribute.size();
            for (int i = 0; i < size; i++) {
                String attributeValue = (String) attribute.get(i);


        return result;

    private DirContext authenticate() throws NamingException {
        return authenticate(null, null);

    private DirContext authenticate(String username, String password) throws NamingException {
        String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
        String securityAuthentication = "simple";

        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
        env.put(Context.SECURITY_AUTHENTICATION, securityAuthentication);
        env.put(Context.PROVIDER_URL, ldapUrl);
        env.put(Context.SECURITY_PRINCIPAL, username != null ? username : MASTER_USER_DN);
        env.put(Context.SECURITY_CREDENTIALS, password != null ? password : MASTER_PASSWORD);

        DirContext ctx = new InitialDirContext(env);

        return ctx;

JavaScript, Assumption Inversion Principle and modularity

On past posts (1, 2) I tried to described what I call Assumption Inversion Principle. Well, talk is cheap, show me the code!

I’m trying to apply AIP on a personal project without infecting (much) the global namespace and going only with raw JavaScript to avoid unnecessary dependencies on things like RequireJS.

That’s the template I have come up with so far (gist):

File...: foo.js
Exports: bar, baz
Depends: spam, eggs
;(function (namespace) {
 'use strict' = function (namespace) {
   /* Dependencies */
   var spam = namespace.spam
   var eggs = namespace.eggs

   function bar () {

   function baz () {

   /* Exports */ = bar
   namespace.baz = baz
}((function () {
  if (typeof window === 'undefined') {
    return module.exports
  } else {
    return window

The file can be used by the browser or as a NodeJS module. At the browser it will register an initialization function on “window” and as a NodeJS module it exports the initialization function.

How to use it? Just include every module and use each initialization function to populate your namespace:

 * Namespace of our app.
var myApp = {}

 * Initialize 'fooDeps' module
 * e.g. registers 'spam' and 'eggs' on namespace

 * Initialize 'foo' module
 * Uses 'spam' and 'eggs' and registers 'foo' and 'bar'

And what do I gain with it? Well, I can treat modules as first-class citizens. Instead of bloating the code with objects and pretty patterns as singletons and factories, each module code knows how to initialize itself, so they are pretty straight forward. As they only use assumptions about their dependencies, the module code easy adapts to other environments. Classic example on single project: production code uses the real dependencies and test code uses mocks or simples objects. On multiple projects, the implementation of each dependency can be selected on whatever reason.

The particular project I’m working on is a Word Finder style game. We use a word dictionary and a random letter generator to populate the board. The random letter generator uses the ratio of frequency of each letter at the dictionary to select the random letters with the same ratio (gist):

;(function (namespace) {
  'use strict'

  namespace.randomlettergenerator = function (namespace) {
    var total = 0
    var lettersArray = []

     * Populates "lettersArray" and computes "total".
    ;(function () {
      var letters = {}
      namespace.dictionaries.forEach(function (word) {
        var i, len, letter
        for (i = 0, len = word.length; i &lt; len; i++) {
          letter = word[i]
          if (typeof letters[letter] === 'undefined') {
            letters[letter] = { letter: letter, count: 1 }
          } else {
            letters[letter].count += 1
          total += 1

     * Sorts by descending letter frequency
    lettersArray.sort(function (a, b) {
      if (a.count > b.count) {
        return -1
      if (a.count < b.count) {
        return 1
      return 0

     * Random letter generator.
    function RandomLetterGenerator () {
      this.lastIx = -1

     * Returns a random letter.
     * @return Random letter.
     */ = function () {
      var i = this.lastIx
      var len = lettersArray.length
      var count = Math.random() * total

      while (count > 0) {
        if (i >= len) {
          i = 0
        count -= lettersArray[i].count

      this.lastIx = i
      return lettersArray[i].letter

    namespace.RandomLetterGenerator = RandomLetterGenerator
}((function () {
  if (typeof window === 'undefined') {
    return module.exports
  } else {
    return window

Notice the module initialization code, it is possible to mock out or use multiple dictionaries to initialize different namespaces with different versions of RandomLetterGenerator class. The same effect is possible using pure OO factory pattern.

Other modules are responsible for finding words and checking board properties. The dictionaries are always an assumption, so the code is easily testable, even without objectifying everything.

I’m currently feeling good with the code. Not sure how it will scale.

Impostor Syndrome

I like to know how to name psychological effects, and I just learned a new one: Impostor syndrome.

This one adds to two others I like: Dunning-Kruger effect and the Bystander effect.

The impostor syndrome is kind of funny, tough. If you recognize that you had passed by an episode of it, then you understand either that:

  1. You are a high-achiever, so you deserve it, so you are cured from the impostor syndrome; or
  2. You projected a false high-expectation from others towards yourself, so you are not a high-achiever, but noone was expecting that anyway; or
  3. You are a fraud.

The only way to figure it out is to really put you up the test. Too bad when you miss an opportunity to burn that feeling.