December 07, 2016

Pitivi 0.98 — Getting there

This is another release focused on fixing bugs and improving stability.

Improved timeline

We switched our official build to use GTK 3.22 and the framework did not like how we were using it, spamming us with warnings in the console. We fixed those and improved the timeline in the process and added more unit tests.

It was quite a journey. Initially, the GTK Inspector was useful to figure out which widgets the widget IDs in the warnings identified. Then we had to go back between the GTK documentation and the #gtk+ IRC channel until we figured out we were changing the size of some containers in their do_draw methods, which was not good.

Accelerated development

Taking advantage of an opportunity, with the last money from our coffers (the remaining 2014 fundraiser donations and the GSoC mentor stipends) we hired Alexandru Băluț, a long-time Pitivi contributor, so he can focus better on fixing issues blocking the 1.0 release. Alex worked on Pitivi in Oct, Nov, and will allocate more time in Dec 2016. Thanks again to everybody who donated!

Customizable keyboard shortcuts

Jakub Brindza, our GSoC 2016 student, finished the customizable keyboard shortcuts feature. See how it works in the screencast below.

Supported muxers and encoders

In the previous version, 0.97, we picked a set of supported muxers, audio encoders, video encoders, added integration tests for them in GES, and changed the rendering dialog to show very clearly the ones which are unsupported.


See what’s left to do for 1.0 in the 0.99 and 1.0 columns in Phabricator. If you want to help in any way, come to our IRC channel. We prepared a nice list of tasks suitable for newcomers. These are good also for students interested to apply for a GSoC with us.

The build system has been ported to meson, no more autogen!😉

November 10, 2016

How to use the x264 encoding presets when rendering an XGES project

x264 has a few generic encoding presets you can use when rendering. You can see the list of presets and exactly what encoding options they specify by running x264 --fullhelp. You'll most probably notice the following presets: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow. Ideally you'd always use veryslow when rendering, but you can't always wait for it to finish, so you go for faster ones. The ffmpeg wiki summarizes the difference between these presets:
veryslow helps about 3% compared to the slowerpreset, slower helps about 5% compared to the slow preset, and
slow helps about 5-10% compared to the medium preset.
To be able to use for example slow with ges-launch-1.0, you need to create a GStreamer preset. Add the following section to ~/.local/share/gstreamer-1.0/presets/GstX264Enc.prs
You need to specify a bitrate in kbits per second because the default value of 2048 kbits per second might not be what you want. I picked 12288 because it's what YT recommends for 1920x1080p50. See the documentation for the x264enc plugin to see all the options you can specify in the preset.

You might also be interested in specifying a tune:
 or a psy-tune:
Other tune values are: film, animation, grain, psnr, ssim. For the list of available tune values see the plugin source code.

To use the new preset, run:
$ ges-launch-1.0 -l pitivi-project.xges -o out.mp4 -f "video/quicktime,variant=iso:video/x-raw,width=1920,height=1080->video/x-h264+slow12mbps:audio/mpeg,mpegversion=1,layer=3"
The -f parameter accepts a serialized encoding profile.

September 26, 2016

Making Viewer UIs for Pitivi

Being someone who has already experimented with two transformation box approaches for Pitivi in the past, maintainers thought I might be the right person to do a modern one.

Creating a user interface for a video transformation requires three things:

  • The implementation of the transformation
  • A way to draw the widgets over the viewer and
  • Mapping the input to the reverse transformation

The transformation

First of all the implementation of the transformation, which is in our case scaling and translation, is currently done by GES.UriSource, calculated on the CPU. In the first Pitivi transformation box I did in GSoC 2012 this was done by the notorious Frei0r plugins from GStreamer Plugins Bad, which is also a CPU implementation. In the second version this was done on the GPU with the gltransformation element I wrote for GSoC 2014.

A method to draw widgets over the viewer

In Pitivi’s case, the viewer is a GStreamer sink. In all three versions rendering of the overlay widgets was done by Cairo, but it was done differently for all three implementations, since they all used different sinks.



2012: The first one used a hacky solution where the sink and cairo drew in the same Gtk drawing area, acquired for GStreamer with the Gst Overlay API. Many Gtk and GStreamer devs wondered how this worked at all. This and Pitivi switching to more modern sinks was the reason why the first version of the box didn’t stay upstream for long.



2014: Still using Gst Overlay API, but this time with the glimagesink. The cairo widgets are rendered into OpenGL textures and composed in the glimagesink draw callback in the GStreamer GL context. Worked pretty smooth for me, but didn’t provide a fallback solution for users without GL. Clearly an approach for the future, but how about something solid?



2016: Now we have the almighty GtkSink in Pitivi. It is a Gtk widget and overlays can be added via Gtk Overlay. The sink is also exchangeable with GtkGLSink, which uses a GStreamer GL context to display the video texture and also can use GStreamer GL plugins like gltransformation without needing to download the GPU memory with gldownload. Cairo rendering now can be easily added over GStreamer sinks, yay.



Linking the UI with the components doing the transformation

The mapping of the input from the UI to the transformation is clearly dependent on the transformation you are using. In the 2012 version I needed to map the input to frei0r^-1. In 2014 I used an OpenGL Model-View-Projection matrix calculated in Graphene, which could also do rotations and 3D transformations (we have a z-axis, yay).

The 2016 implementation uses the inverse transformation for the GES.UriSource transformation, which is done by the GStreamer elements videomixer and videoscale. Of course things like keeping aspect ratio, maintaining limits and transforming Gtk widget coordinates to the transformation’s coordinates are part of this 3rd ingredient.



The new transformation box fits great with Pitivi by making clips selectable from the viewer, so you can manage multiple overlapping clips quite easily. But the best part of this implementation may be its extensibility. I already made two overlay classes, one for the normal clips which uses a GES.UriSource transformation and one for title clips aka GES.TextSource, which is using different coordinates and different GStreamer plugins. In this fashion other plugins can be written for the Pitivi viewer, for example for 3D transformations with gltransformation. Or you could do crazy stuff like a UI for barrel distortion etc.

Clone the code and contribute! 🙂


If you have any questions about this ask me. I’m lubosz on Freenode IRC.

August 23, 2016

GSoC with Pitivi

Customisable keyboard shortcuts for Pitivi
Google Summer of Code 2016 Summary

Over the summer I have been working on customisable keyboard shortcuts for Pitivi. Below, I am including an easy-to-read and concise summary of every bit of work I have done over the last three months.

The summary of all the code I have written can be found at:

The work above contains these key elements:
  • Refactor the code to use Gtk.Application.set_accels_for_action() in order to create the base for customisation.
  • Use the Gtk.ShortcutsWindow widget to allow the user to preview the keyboard shortcuts.
  • Refactor Pitivi’s Preferences dialog to use Gtk.StackSidebar.
  • Add keyboard shortcuts section to the Preferences dialog with a selectable list of all the shortcuts in the application to allow customisation.
  • Implement saving of shortcuts to an external configuration file for the case when a user changes the default shortcut settings.
  • Implement loading of saved accelerators from the configuration file and ignore the default accelerators when this happens.
  • Create a ShortcutsManager class dedicated to storing and handling of the accelerators. It is used for registering keyboard shortcuts in appropriate categories and their consequent management.
  • Fully support the ShortcutsManager class with tests, mostly using the Mock library.
  • Implement the customisation of accelerators via a separate dialog window opened after user's selection in preferences.

Blog posts describing all of the aforementioned work can be found at:

At the very end, I would like to specifically thank Alexandru Bălut for his great mentorship, valuable pieces of advice, willing approach towards answering my questions and, most importantly, for making me a better software developer.

August 21, 2016

GUADEC 2016, laptops and tablets made to run GNOME, surprise Pitivi meeting

I went there for the 2016 edition of GUADEC:


I arrived a couple of days early to attend my last GNOME Foundation board meeting, in one of the KIT’s libraries. The building’s uncanny brutalist architecture only added to the nostalgia of a two years adventure coming to an end:



And so I made a new talk proposal at the last minute, which was upvoted fairly quickly by attendees:


The conference organizers counter-trolled me by inscribing it exactly like this onto the giant public schedule in the venue’s lobby:


The result was this talk: Laptops & Tablets Manufactured to Run a Pure GNOME. Go watch it now if you missed it. Note: during the talk’s Q&A session, I mistakenly thought that Purism‘s tablets were using an ARM architecture; they’re actually planned to be Intel-based. And to make things clear, for laptop keyboard layouts, Purism is currently offering US/UK, which are different physical layouts (different cutting etc.).

Also relevant to your interests if you’re into that whole privacy thing:

In my luggage, I carried ~20 kilograms of the Foundation’s annual reports. Some folks were skeptical and thought I should “only bring a few of them, people aren’t usually interested in the annual report.” Well, they were dead wrong: within one afternoon, the annual reports “sold out” like hotcakes. See also my tandem lightning talk (at the 29mins mark) to get a glimpse of how much work we put into designing the new annual report this year. Also, if you took one of them at the conference, remember: they’re precious little works of art and a powerful tool to convince people to become contributors or sponsors to support GNOME, so make sure to use them towards that goal!

I was very happy to see Mathieu and Alexandru from the Pitivi team deciding to attend at the last minute, even if it was just for one day. We spent time with Jakub Steiner discussing his workflow and wishlist for a “perfect” video editor:

2016-08-15--17.05.53Pitivi makes people smile!
Left to right: Alexandru Băluț, Jakub “Skywalker” Steiner, Mathieu Duponchelle.

I took a handful of photos of the BoFs and uploaded them to my gallery for GUADEC 2016. Licensed under the Creative Commons “by attribution” 4.0 as usual, so that the GNOME Engagement team can use them for GNOME promotional materials if needed. Make sure you do the same and list yours in here.

The Flatpak BoF sessionThe Flatpak BoF session

Overall, this GUADEC was one of the most well-organized ones I’ve seen in years. I was floored by the amount of efforts and planning the local team put into this. They really deserve some kudos! Everything ran smoothly on the surface (I know that in such events there will always be odd situations happening here and there, but they dealt with them so efficiently that they were invisible). The team had a professional-grade two-way radio system to coordinate, a car and trailer to carry stuff around every day, made and reused food (pro-grade cafeteria counter metal containers = genius), a lifetime supply of IKEA mugs that got washed and reused frequently, tons of snacks, managed to pull in great sponsors even at the last minute, put signage in various parts of the city to guide people to the venue, had huge quantities of tasty dead animals (and plants) to eat at a very successful barbecue event, got an icecream vendor to come to the venue, and even filled up a pool and beanbags, for pete’s sake!

Thanks to the the Chaos Computer Club for providing a flawless live video streaming, recording and publishing service. Very rarely did we have GUADEC videos published in a timely fashion in the past, let alone streamed live and with proper laptop video output capture as well as proper sound mixing. This is fantastic.

I should mention the closing night’s event in the biergarten, with sponsored drinks and food by our friendly GStreamer experts Centricular, a very nice gesture that was well appreciated by everyone.

2016-08-15--19.23.28Survivors at rest in the snacks bunker on the last day of the BoFs

Thanks to everybody involved to make this event a success, and thanks to the GNOME Foundation for making it possible for me to attend.

gnome sponsored badge shadow

August 02, 2016

Save. Load. Reset. Shortcuts get new functionality.

In the recent days, I have been working on implementing the functionality behind saving and loading of custom shortcuts. Moreover, Pitivi's save logic can store the shortcuts in an external file, which holds the user's preferred settings. This file's contents can then be loaded and used to fill the Shortcuts Window - if the file exists. If it does not exist, Shortcut Manager class will simply use the default accelerator settings.

Secondly, I made a step forward in implementing the reseting functionality for the shortcuts. Whenever a user has customised shortcuts, she'll be able to reset it to Pitivi factory settings by a single click of a button. The important point here is that the back-end functionality for this button has just been implemented and so we are ready for putting it all together to some nice UI. It was important to define the logic of storing the default shortcuts, so that we have them accessible at any time, even if user decides to change all of them. Thanks to this, we are ready for reseting the shortcuts at any point in time.
Users will be able to reset either a particular action's accelerators, or reset them all by a single click.

Furthermore, I was able to practice unit testing a lot. For all the pieces of work - save, load and reset functionality - I provided unit tests with fairly extensive use of mock library. I learnt a lot through this, since I have to admit at the very beginning the idea behind what kind of tricks mock is actually doing behind the scenes was hard to understand for me. By now however, Pitivi has a code of good quality for all the work I have done (Alex thanks for the excellent reviews) supported by relevant tests.

So what is next?
Over the course of this and the next week, I will be concentrating on the UI primarily and bringing all the little pieces of work I have done together. Hopefully by the end of this week, I will be able to present an implemented and working UI for the Preferences shortcuts section and also add the reset buttons to reset one or all shortcuts.

July 18, 2016

Get Pitivi directly from us with Flatpak

Distributing apps as packages (deb, rpm, etc) is problematic. For example, the Pitivi package depends on the GTK package and Pitivi 0.95 broke in the distributions which updated to GTK version 3.20, because of the incorrect way we were using a virtual method. This is not the first time something like this happens. To avoid the slippery dependencies problem, two years ago we started making universal daily builds. They allowed everybody to run the latest Pitivi easily by downloading a large binary containing the app and all the dependencies.

A few problems still remained:

  • It was complicated to set up the Pitivi development environment. We had a huge script for setting up the development environment and new contributors always had problems. We tried to reuse the daily builds for preparing a development environment but it was hacky and we failed to make it work correctly.
  • Users were notified about available updates through a custom mechanism and updating was not ideal, requiring to download a huge binary blob.
  • Maintaining the AppImageKit based bundle required following many dependencies (security) updates and maintaining the build for them (even though we were sharing the burden with the whole GStreamer community, as we were using the Cerbero build system).

Recently Flatpak got our attention as it set out to fix these problems. Flatpak’s sandboxing allowed us to create a nice development environment. Our new dev env script reuses the one which flatpaks Pitivi so we got rid of the old ones. Also, Flatpak allows the user to only download binary diffs for updates. Moreover, the Gnome community already provides builds for their SDK and Runtimes, which contains almost everything we need for Pitivi; now, we only have to build a few libraries, which makes it much simpler for us to maintain the new bundles.

We’re enthusiastic about Flatpak. Jakub Steiner summarized Flatpak’s advantages very nicely:

Flatpak aims to solve the painful problem of the Linux distribution—the fact that the OS is intertwined with the applications. It is a pain to decouple the two to be able to:

  • Keep a particular version of an app around (and working, our note), regardless of OS updates. Or vice versa, be able to run an uptodate application on an older OS.
  • Allow application authors distribute binaries they built themselves. Binaries they can support and accept useful bug reports for. Binaries they can keep updated.

For now you need to use the command line to install Pitivi with Flatpak. In the near future, it should be trivial for you to install and manage our Flatpak build of Pitivi in your favorite software manager. GNOME Software is a good example.



July 11, 2016

Meet me halfway [of GSoC with Pitivi]

Hi everyone, it's been a while but I am back now with a short update on my work on Pitivi's customisable shortcuts.

Without too many words, this is the state of the shortcuts window after my recent works to add some forgotten shortcuts:

However, more interesting things happened on the back-end side of Pitivi.

I refactored the shortcuts logic, preparing everything for the implementation of shortcuts customisation. From now on, instead of the ShortcutsWindow class which originally handled both populating the window as well as gathering the data, Pitivi now features a dedicated ShortcutsManager class besides the ShortcutsWindow class.
This way, I could reach a more straightforward and less cluttered organisation of code with one class used only for displaying of the window while the other is handling data gathering and its storage.

This important step allowed me to move forward and start working on loading and saving of the shortcuts preferences. I am aiming for an implementation where by default, all shortcuts will be set from the code, however, once a user changes even a single shortcut, all of them will immediately be stored in an external configuration file which will be loaded from that point onwards and the default shortcuts will be ignored.
I decided to apply TDD for this part. I started with writing the tests and in the upcoming days I will be taking care of defining the loading and saving of shortcuts logic.

I think it will be very exciting, I can't wait to see the customisation working already and this is a very important step so I want to do it the best I can so that my progress increases every day and Pitivi users can enjoy shortcuts customisation as soon as possible.

June 30, 2016

Pitivi 0.96 — Cogito Ergo Proxy

Besides the usual cleanup and bug squashing, this release brings a fundamental feature which greatly improves the edit experience. Now you can edit and render a video project with any video files with great accuracy, thanks to proxy files.

Proxy editing: fast and accurate editing with any video format

The harsh reality of this world is that there is only a limited set of formats that really work well for video editing. Without those, rendering a project could have been inaccurate at times*. The user experience degrades when using container formats not designed for fast & accurate seeking. For example, seeking a video format where the keyframes are followed by one or more inter-frames (such as in VP8, H.264) is often slow.

To provide the best experience, we decided to give you the ability to seamlessly work with media formats suitable for video editing. This is accomplished with what we call “proxy” files. Other video editors advertise the use of downscaled proxy files which, besides the improved reliability, also provide better performance when the system is not powerful enough to handle high-quality video files in real-time.  We do not cover the the downscaled proxy files case yet—that’s planned for post 1.0. For now, our proxies are high-quality proxies intended to be used instead of the original, when editing and also when rendering the project.

Oh, and since we’re so smart, we now also generate the audio waveforms and filmstrip thumbnails at the same time as we are processing proxies. Super efficient.

So what is the difference between an original and its “proxy”? The proxy is a slightly degraded but easier-to-work-with version of the original:



Okay, okay, we might be stretching the analogy a little bit, but you get the picture.

When are proxies needed for stability?

The whitelist below shows the formats we officially support—which can be used safely without proxying them. For the rest, we recommend using proxy files to guard against bugs in the decoders and demuxers. Depending on how popular other formats get, we will consider officially supporting them. The intention is to keep the list short to avoid spending too much time on decoders and demuxers.

At the moment, the whitelist is comprised of the following:

  • Containers: QuickTime, Ogg, Matroska, WebM
  • Video codecs: H.264, MJPEG, VP8, Theora, raw
  • Audio codecs: Opus, MP3, Vorbis, FLAC, raw

How does it work?

When you import an asset with an unsupported format, it is by default transcoded using a codec suitable for video editing. You can disable or force the proxy creation on a per-asset basis, when you import or later at any time. Finally, when rendering, you can specify whether to use the proxies or the original files. You are always in control.

image07.pngOptions when importing files
Options for already imported video files
image08.pngOptions when rendering a project

As seen in the screenshots above, the state of an asset’s proxy is shown by an icon in the bottom-left corner of the asset thumbnail, in the Media Library. The icon can be one of:

  • none    The original is used.
  •         The proxy is being created by transcoding the asset.
  •         The proxy is ready and is used automatically.
  •         The proxy creation failed and the original is used.

The main disadvantage of using the intermediate proxy files for rendering is that some quality is lost when transcoding, but this is not noticeable in most cases. Other than that, transcoding the originals takes a bit of time and they take some disk space (around 10 times more for H.264 content, for example). In practice, we think that using proxy files is the best option. You decide what works for you but take into account what is considered safe and officially supported, and what is not.

It was very important to pick a codec that preserves the visual quality of the originals, so that final renders can be done out of the intermediate proxy files with no perceived quality loss. The other requirement was that seeking should be fast, meaning it had to be an intra-frames-only codec, where a frame is encoded and decoded independently of any other frame. Currently Pitivi uses MJPEG or ProRes for the proxy files, depending on which is available on the system.

For now, the audio is transcoded using Opus, even though it’s a lossy format, because the codec is very good. We’ll most probably switch to FLAC when it will be more supported in GStreamer because it loses no quality and has a pretty good compression ratio.

Scrubbing the timeline easily

Currently the user is able to select, move and edit clips by using the left mouse button. This is exactly how a user expects to interact with a GTK UI and it works very well. In addition to that, when clicking using the left mouse button, a seek is performed and the playhead is moved to that position. Some users were annoyed by this combined behavior so we added an option for disabling seek on left-click, but this was not enough.

Inspired by Blender’s different functionality assignation for left and right mouse buttons, we added the ability to seek by right-clicking. Now you can quickly and safely scrub on the timeline as well on the ruler using the right mouse button. Since Pitivi did not provide a context menu when right-clicking on the timeline, it was easy to make this possible. Try it out and let us know what you think. More details on the reasoning that led to this are visible in T3158.

Transformation box

The transformation box is back, thanks to Collabora and Lubosz Sarnecki! This is the third implementation of the transformation box, first one being hacky and second one being available only for users with GL video cards. Now it works great due to the almighty GtkSink, GStreamer’s latest GTK widget for displaying video.

The new transformation box fits great with Pitivi by making clips selectable from the viewer, so you can manage multiple overlapping clips quite easily. But the best part of this implementation may be its extensibility, an example being the module for the title clips.

image01.pngTransformation box around Alex’s parents’ cat’s best friend

Project settings: letting the computer figure things out

At least one of our contributors felt intimidated when he first saw the project settings dialog which used to show up when creating a new project. The project settings define how you preview the project while editing. You might want for example to choose a small video size if your computer is not very powerful, then at render time change that to get the best quality. These settings can be changed safely at any time.

The question was whether showing that dialog is really necessary at that point in time. Well, not really. Now, when you create a new project, some default values are set and then when you import the first video file, its properties are transposed to the project settings.

The logic is thus: either users don’t really care about the project settings and the “Project Settings” dialog showing up when creating a new project overwhelms them, or the user is an experienced videographer, in which case they’ll know when they need to change the project settings and where to find them. A very nice touch is that when the project settings are changed automatically, an infobar appears, so the user has the chance of opening the project settings and correct them if need be. More details in T3161.

image06.pngInfobar when the first clip is imported

New project settings and rendering UI

The widgets in the project settings dialog and the rendering dialog were split into multiple tabs, to fit on 1024×768 screens. Unfortunately this required clicking the tabs to see or edit the settings. Moving the eye is faster than clicking so we looked into this and came up with a solution to get rid of the tabs and keep the dialogs as small as possible.

The preset selection UI is now composed of a ComboBox plus a MenuButton. This way the preset selection UI takes extra vertical space instead of extra horizontal space. We find it works pretty good. More details about how it works and more screenshots in this doc.

image09.pngThe Project Settings dialog
image03.pngThe Render dialog

Keyboard shortcuts window

Jakub Brindza joined us as a GSoC student. The first step of his project is already done, a brand new keyboard shortcuts window built dynamically, to be able to support custom shortcuts. Next will be allowing users to customize the keyboard shortcuts.

image04.pngThe Keyboard Shortcuts window

Other noteworthy changes

  • The user manual has been updated to reflect the changes since we switched to the headerbar, about one year and a half ago.
  • The undo/redo removal has been undone.
  • We switched from AppImage to Flatpak to distribute our own builds. A big advantage is that due to Flatpak’s sandboxing we can use it for the development environment while previously we needed a separate complex script to take care of that.

* There was a very high chance of ending up with artifacts at the start of a clip with an inpoint.

June 21, 2016

Pitivi featuring Gtk.ShortcutsWindow - phase 1 complete!

After nearly a month of work on Pitivi, the project has moved forward by quite a bit. Pitivi now contains the all-new Gtk.ShortcutsWindow which is build up dynamically from various places across the app. 

First of all, reaching the current state would be impossible without refactoring the way accelerators were added to the Pitivi app. The documentation for this is not very detailed, however after some research with Alexandru Băluț, we found a solution in dropping the previously used Gtk.Application.add_accelerators() in favour of the current Gtk.Application.set_accels_for_action(). This created the basis for achieving the next goal, the customisation.
At this point also, I believe it would be appropriate to thank this way to lazka for the excellent work done on Python documentation as well as providing hints on how to build the shortcuts window dynamically. Secondly, Christoph Reiter deserves a credit since his implementation of how to build up shortcuts window was an excellent starting point for me, too, to better understand the structure of the desired implementation. 
For a preview of my implementation of shortcuts and shortcuts window utilising them, take a look at the following commits of mine:

Link 1: Refactoring to Gtk.Application.set_accels_for_action()

Link 2: Dynamic build-up of the Shortcuts window

The importance of this implementation is in the fact that now my steps are moving on to implementing customisation of shortcuts via Preferences, invoking a change in the Shortcuts Window after each customisation of any shortcut by the user. This dynamic build-up of the window will enable us to make sure users always have the most up-to-date details of their preferred shortcuts settings always at a hands distance. The Shortcuts Window is available from various places across the app - immediately from the welcome wizard window, from the menu inside the app, as well as simply by pressing Ctrl + ? or Ctrl + F1.

This way, users will never have to struggle with how to become more effective at using Pitivi. All the information is neatly presented right in the app, no need to go anywhere else.
Below is a small sneak peek of the newly-implemented feature:

Pitivi shortcuts window contains 2 pages of well-described shortcuts, natively supporting search too (courtesy of Gtk implementation :) )

Along the way, the code behind Pitivi gets some minor refactoring every now and then. I learnt a lot about the way inheritance, overriding, tests and other cool features work in Python, which is excellent as it enables me to learn a lot of interesting stuff.

Next on schedule is customisation, but prior to that, I'm refactoring the Pitivi Preferences window to utilise Gtk.StackSidebar for neat, modern organisation of all the current, and soon-to-be-added settings - the shortcuts settings - for the app. 
Stay tuned!

June 15, 2016

Working for Collabora Multimedia :)

This month is my first month working (part time) for the multimedia team at Collabora. I think you all know about this company which is specialized in open source softwares particularly in Gstreamer and all majors Gnome/Freedesktop technologies.

So I am now working on GStreamer related technologies and in particular on PiTiVi to make it rock more and more!

I am very glade to be part of this team and am looking forward the good time I am going to have hacking as a multimedian :)

May 24, 2016

Customisable shortcuts. Enhanced experience. Ctrl + P[ itivi ]

My second Google Summer of Code participation has just begun and I am very excited to share some of my new goals, plans and ideas.

First of all, I am challenging myself to try to keep my posts concise, on-topic and compelling as I want to brush up on the art of blogging as well as develop my language skills.

Thus, without further introduction, what lies ahead for me during the upcoming 3 months?

I will be contributing to Pitivi video editor under the flag of GNOME Organisation. I am going to work with Alexandru Băluț who is my mentor, as well as many other Pitivi contributors whom I already found to be very helpful and easy-to-talk-to people. :)
My task is to implement customisable shortcuts to the application and slightly more verbose abstract of my work can be found at the GSoC 2016 website.

Primary goals:
  • Refactor existing shortcuts to allow customisation using Gtk.AccelMap
  • Write tests for all the existing shortcuts in order to guarantee their correctness
  • Introduce the new GTK feature, GtkShortcutsWindow, to organise the shortcuts in an elegant and modern way
  • Implement the customisation of shortcuts via Preferences enhanced to use Gtk.StackSidebar for clarity
  • GtkShortcutsWindow to automatically update itself after users change their shortcut preferences
  • Define new shortcuts for JKL navigation along the timeline
I am honestly looking forward to the following few months as I expect and hope to learn about technologies and concepts I have not known before (Flatpak), extend my knowledge in areas I have some rudiments in already (Python, GTK, Git, Linux) and most importantly enjoy what I am going to do. 
I will be doing the best I can and hope to see the Pitivi community appreciating my work at the end of the summer.

Stay tuned to hear more about Pitivi development!

April 18, 2016

Polishing Pitivi's ruler

In Pitivi, the ruler is displayed above the timeline to show the times corresponding with the current view. A series of H:MM:SS.XXX timestamps on a ruler might leave the impression that only trained professionals are supposed to use it. I had trouble reading the timestamps and looked for ways to make the ruler more useful. Read below for the story.

Pitivi ruler, Dec 2013

Relevant parts

Around the New Year 2013-2014 I thought about highlighting the relevant parts in the timestamp. For example, if you have 0:00:05.000 and then 0:00:10.000, you have to look quite a bit until you notice what changes from one to the other. In this case the "10" should be highlighted because that's different than the previous timestamp. This way it's easier to see what an interval represents. Jeff liked the idea and the commit went in.

The ruler being more useful, I started to look more at it while using Pitivi. One week later, after 6 code cleanup commits, the millis were being displayed with a smaller font, so they can be ignored more easily. One hour later though, the hours and millis were being displayed only when useful:
  • The hour is displayed only if greater than 0. 
  • The millis are displayed only when the zoom level is high enough that millis other than “.000” start to show up in the timestamps. This got improved later!
The shorter timestamps looked good so the changes went in.

Guessing most projects are less than one hour long and most of the time users don't use zoom levels where milliseconds matter—this was already a big improvement, it’s much easier to see “MM:SS” than “0:MM:SS.000”.

Pitivi ruler zoomed out, Jan 2014

Dividing an interval

An “interval” on the ruler is the interval at which the timestamps are shown. At different zoom levels, the length of the interval is picked automatically out of a hardcoded list, so you see an optimum number of timestamps. It was awkward that the displayed intervals were always divided in 10 parts. While it makes sense for a 10 seconds interval to be divided by 10, it’s not very useful when a 30 minutes interval is divided by 10.

It was easy to define the tick frequency for each of the hardcoded intervals, but it looked awkward for most of the zoom levels. Previously we clearly preferred largish interval sizes (so the interval can be divided in 10 smaller but still visible units) but it was not so nice anymore when a large interval is divided only in 2 units. Some fine-tune of the minimum interval length and the minimum division length was required. The smaller timestamps fit great with the smaller intervals:

Dividing by 2 is enough for some intervals, Dec 2015

Timestamp shape

While fine-tuning the minimum interval and interval division size, I realized that when displaying millis, it’s useful to display only the millis, except for the full second timestamps when only [H:]MM:SS is displayed. This way it’s much easier to see where the full seconds are, because “00:01” looks quite different shape-wise than “.500” which is displayed with a smaller font. Luckily, by keeping all the timestamps short (“.900” is the shortest and “9:00:00” is the longest), it was possible to have a simple formula for choosing the optimum interval per zoom level.

Pitivi ruler zoomed in, Jan 2016

The commit went in, along with a cherry.

Some did not like the pear-shaped playhead though, so we later replaced it with an empty diamond.

Pitivi playhead, Apr 2016

Start Pitivi and look at the ruler, zooming in and out, a nice feeling starts bubbling up inside.

Until we wrap up 0.96, you can already see the ruler in action by downloading the Pitivi bundle! BTW, the bundle already includes the proxy files functionality which allows using any video format reliably. Read: no more artifacts when using MTS files. When compared, the ruler polishing I described above is just me playing in the sand. The proxy files functionality brings Pitivi much closer to 1.0. Please try it out and tell us how it works for you! :)

If you are still here, see maybe the entire history of Pitivi’s ruler.

February 22, 2016

Back from the DX hackfest

Back from the DX hackfest

I had the chance to attend the GNOME developer experience hackfest three weeks ago, I’m ashamed to admit three weeks went by before I took the time to write this post!

A lot of people I met there I already knew, I was happy to meet some people I didn’t yet, like James, who’s working on Oh-My-Vagrant.

Philip Withnall has already done a good job at summarizing the general issues we looked at as a group during this hackfest in this blogpost, so this post will revolve around my own experience over there.

I am currently working on hotdoc for collabora, and I spent the hackfest presenting it to the documentation team members (Ekaterina Gerasimova, Frédéric Péters, Bastian Ilso and Alexandre Franke), discussing its future use with them and Philip Chimento, and making some improvements to it with the help of Thibault Saunier.

Hotdoc improvements

I helped Frédéric with testing porting gtk from gtk-doc to hotdoc, and landed a patch from him in hotdoc-gi-extension, the resulting documentation seemed overall correct.

I worked with Thibault Saunier to implement a smart include feature in hotdoc.

GNOME Builder

I discussed how to use hotdoc as a GNOME Builder plugin with Christian Hergert, but the solution he advised me to follow actually falls short because hotdoc is python2, and it seems libpeas cannot handle both python2 and python3 in the same process. I’m still a bit confused as to why this limitation would exist, as the proposed solution involved exposing a D-Bus service, but I’m sure we’ll find a better solution when we need to.

GNOME developer portal

I discussed the future of with the documentation team. They liked the search interface in hotdoc (it does work quite well :), and we all agreed that a tighter integration with actual API references would be nice to have, amongst various other things (online editing for example).

The website is currently implemented as a series of mallard pages. Hotdoc does not read mallard pages, and it isn’t part of my current plans. A possible way forward would be to drop mallard altogether, and have all the pages be “hotdoc-flavored” markdown pages. I think this could make sense because:

  • gnome-devel-docs doesn’t make an extensive use of mallard.
  • markdown pages present a significantly lower barrier to entry, and most people are familiar with the syntax.
  • the developer site and the API references it would link to would share the same format for standalone documentation source files.

I have since then implemented a simple pandoc reader, and used it to make a very naive port of gnome-devel-docs, the result can be seen here

This port is naive because I made absolutely no manual edits to the produced markdown files, which explains why the index page looks pretty ugly, but pages like are pretty faithful to the source, and it would mostly be a matter of custom CSS and trivial edits to get the thing to really look good.

You can have a look at the generated markdown files here.

Philip Chimento’s devdocs work

Philip Chimento has been working on a fork of devdocs, in an effort to create a javascriot developer portal for GNOME. I see some drawbacks with his approach, which we’ve discussed together and I will not detail here, but overall his current solution has the advantage of code reuse, and lightweightness, as the output is generated stictly from gir files.

My opinion on this is that his work is a nice short-term solution to a clear problem (gathering together the javascript documentation for most (all ?) GNOME libraries, and I suggested linking to it on the current portal.

However I think the design of devdocs and his solution will fall short for the long-term requirements that the GNOME documentation team seems to set, and Philip seemed to agree.

This is still a very open issue, and Philip and I definitely intend to work together to provide the best possible experience for GNOME hackers, newbies and senior alike.

November 19, 2015

Pitivi 0.95 — Enfant Suisse

Hey everyone! It’s time for a new Pitivi release, 0.95. This one packs a lot of bugfixes and architectural work to further stabilize the GES backend. In this blog post, I’ll give you an overview of the new and interesting stuff this release brings, coming out from a year of hard work. It’s pretty epic and you’re in for a few surprises, so I suggest listening to this song while you’re reading this blog post.

Engine rework: completed.

Those of you who attended my talk at GUADEC 2013 might remember this particular slide:

kill gnonlin

Well, it’s done now. It’s dead and buried.

This is something I’ve had on my mind for so long, I was even having nightmares about it—literally. To give you an idea just how ancient gnonlin was from an architectural standpoint, it was created fourteen years ago, merely six months after the first release of GStreamer itself. Well, y’know, a lot of stuff happens in 13-14 years.

So, over the past year, Mathieu and Thibault gradually refactored GNonLin into NLE, the new non-linear engine inside GES. For details, see the previous two blog posts about our War Against Deadlocks: the story about the mixing elements and the story about the new engine using them (replacing gnonlin).

The resulting improvements in reliability are not only palpable in daily use, they are actually quantifiable with the results our GES gst-validate test suite runs:

  • In the 1.4 series: 154 tests pass out of 198 (22.2% failures)
  • With the 1.6 release: 198 tests pass out of 198
— "What's going on? Give me a sitrep!" — "The tests… they all pass!" — "What?!"— “What’s going on? Give me a sitrep!”
— “The tests… they all pass!”
— “What?!”

Now 100% GTK, with new horizons

pitivi 0.95

We were hitting various limitations and bugs (such as this) in Clutter, the library we used to display and animate the project’s timeline. Eventually we came to a point where we had to change strategy and port the timeline to use pure GTK+ widgets, with Matplotlib for drawing the keyframes on clips. Quite some work went into the new timeline.

The viewer (the widget that shows the main video preview, above the timeline) using glimagesink was causing too many problems related to embedding in the X window. We switched to the new GtkSink instead, which also allowed us to test gtkglsink at the same time, as they are compatible.

Thanks to the new GTK timeline, we have a little surprise to show here: technically, Pitivi can also work on Mac OS X now. This is not an April Fool’s joke.

Some notes about the experiment are sitting there if you’re curious. At this time, we are not supporting the Mac OS version officially, because we don’t have the resources for that (yet?). I was told that we should be able to make something available for testing a Mac build once we reach 1.0. Want to make it happen sooner? Feel free to join us and to work on that.

Wait, that’s not all. These changes also allow us to make Pitivi work with the GDK Broadway backend, meaning we can even run Pitivi in a web browser! Yep, you heard that right. Pitivi in a web browser. What could possibly go wrong? ;)

Spit polishing

An improvement we’re quite happy about is that you can finally drag & drop a file from a different app directly to the timeline, to create a clip.

The layers’ representation changed somewhat. Previously, an audio-video clip would be displayed as two separate clips in the timeline, one for video and one for audio, on two separate layers. At times it was pretty awkward. While porting the timeline, Thibault simplified the layers model to have the notion of generic layers, in which audio-video clips are represented as a unified clip object. This also means that there is no more wasted space if the layer has only video or only audio.

Also worth mentioning:

  • We have resurrected the transformation box feature, but the UI is currently very primitive. See the Clip properties > Transformation section when a clip is selected on the timeline. You can also drag the image in the viewer to change the position of the selected clip at the current position and you can use the mouse wheel to zoom in/out.
  • While editing a project, every operation is saved in a scenario file. These can be used when reporting bugs. See how to use scenarios for reporting complicated bugs easily (or if you’re feeling geeky, the details about how the scenarios are used to automatically test the GES backend).
  • You can now copy/paste clips in the timeline.
  • We’re now compatible with smaller screen resolutions (such as 1024×768) again
  • We removed a bunch of widgets in the layer controls. They were placeholders for future features, we should put them back once the features actually become available.
  • Undo/redo has been disabled until we add unit tests and make sure it works properly. Until then you can Ctrl+S regularly.
  • See also the release notes for 0.95.

Infrastructure changes

  • The Pitivi team migrated from Bugzilla to Phabricator for bug/task tracking.
  • We now have a script to setup the development environment from the latest daily bundle. This hybrid approach makes it very easy for new developers to start hacking on Pitivi’s Python side without needing to build the rest.
  • It was difficult for us to keep using Dogtail, so we moved all the integration tests to GstValidate.
  • Some of you have suggested that we compress the all-in-one bundles using XZ, and so we did. Our packages are now 20% lighter than uncompressed tarballs, so they will take less time to download (which is nice if you’re using the dailies to test).
  • With some help from Jeffrey Schroeder, I have finally upgraded our MediaWiki instance to the latest stable release. We hadn’t upgraded it in four years (thankfully it was fairly locked down so we did not run into trouble), in big part because it was not version-controlled and thus was a pain in the butt to manage. I should be able to do a better job at keeping it up-to-date from now on.

Where do we stand on the fundraiser?

In terms of donations, less than the fundraiser’s first milestone was reached. Therefore, instead of working full-time and burning through the money in a matter of a few months, Thibault and Mathieu decided to work at a slower rate while simultaneously providing professional multimedia consulting services to put food on the table.

Nonetheless, they eventually reached the point where they had worked through all the donated funds, and so they continued in their free time. The GTK+ Timeline and GtkSink work, for example, is one of the big architectural changes that Thibault had to do on his spare time, without monetary compensation whatsoever.

Now is still a good time to let others know and ask those around you to donate! We appreciate it.

A call for ruthless testing

As it is much more stable already, we recommend all users to upgrade to Pitivi 0.95 and help us find remaining issues, if any. Until this release trickles down into distributions, you can download our all-in-one bundle and try out 0.95, right here and now. Enjoy!

You’re in luck: I already spent a lot of my (very limited) spare time testing and investigating the most serious issues. In fact, one of the reasons why it’s been so long since the last release is that I have been Thibault’s worse nightmare for months (there’s a reason why my name strikes fear in the hearts of GStreamer developers):


Every two weeks or so, Thibault would come to me and say, “Hey look, I fixed all your bugs, how about we release now?”. I would then spend a day testing and return with ten more bugs. Then he would fix them all, and I would find ten other bugs in different areas. Then he would fix them, and I would find another batch that I couldn’t test last time. And so on and so forth, from spring to autumn. For example, these are the bugs I’ve found just for the GTK Timeline. Can’t believe I haven’t killed that poor guy.

Now that the blocker issues are solved, I’m quite impressed with how much more reliable this version of Pitivi is shaping out to be now. But hey, we’re not perfect, maybe there are bugs we’ve overlooked, so please grab 0.95 and try to break it as hard as you can, reporting the issues you find (especially freezes, crashes, incorrect output, etc.). We want it to be solid. Go wild.

office space printer

Thank you for reading, commenting and sharing! This blog post is part of a série of articles tracking progress made with work related to the 2014 Pitivi fundraiser. Researching and writing quality articles takes a lot of time, so please be patient and enjoy the ride! 😉
  1. An update from the 2014 summer battlefront
  2. The 0.94 release
  3. The War Against Deadlocks, part 1: The story of our new thread-safe mixing elements reimplementation
  4. The War Against Deadlocks, part 2: GNonLin's reincarnation
  5. The 0.95 release, the GTK+ timeline and sink
  6. Measuring quality/reliability through time (clarifying what gst-validate is)
  7. Our all-in-one binaries building infrastructure, and why it matters
  8. Samples, “scenario” files and you: how you can help us reproduce (almost) any bug very easily
  9. The 1.0 release and closure of the fundraiser

October 20, 2015

Pitivi moves from Bugzilla to Phabricator

Using Bugzilla to manage Pitivi was a bit painful and we were looking for a replacement. Many projects seemed to switch to Phabricator lately, which looked like a very good platform for managing projects. We experimented migrating Bugzilla bugs to Phabricator, and we are pretty content with the result. The UI is nicer, we have a better search function, and the Git integration (with the code review component) works great.

We decided to make the switch official, so we updated the documentation on the wiki and website to link to Phabricator, closed the Pitivi Bugzilla “product” and closed the remaining bugs in Bugzilla with a custom made script. The script also linked each bug to the proper task in Phabricator.

For those new to Phabricator, remember that instead of creating a “bug” you create a “task”.

October 16, 2015

The War Against Deadlocks, part 2: GNonLin’s reincarnation (the other thousand Deadlocks)

GNonLin has served our cause well for a number of years, but was left with indelible marks from the Old World. We grew increasingly worried with GNonLin’s common affiliation with Deadlocks, to the point where it was known as “the Baron of Deadlocks” by our battalion. We tried correcting it, tried reasoning with it, but alas—we only got “not-negotiated” caps errors.

A swift operation took place. The baron was captured and we applied a mix of heavy persuasion and alchemy, until it renounced its questionable affiliations and was reborn. The rise of the Non Linear Engine (“NLE”) plugin brought much joy in the county. Users are no longer harassed by renegade Deadlocks as they peacefully seek along their timelines. The Deadlocks may still try to haunt us, but it’s a whole New World, in which old tricks won’t affect us anymore.

Pictured: "The Capture of the Baron"

In the words of the Maintainers:

We reused parts of the videomixer plugin to create the compositor plugin, which, in comparison, is thread safe. The new compositor plugin is already used by quite a few multimedia apps. In this process we created a new base class, which helped rewriting the audiomixer plugin to fix it and make it thread safe. This allowed us to switch from using adder to using audiomixer.

As you might know, the GStreamer plugins are used for creating pipelines, for example: (video1 * effect1) + video2 = x. The compositor plugin implements the + in this equation. A pipeline is used by NLE to play a video project. NleComposition translates a project’s timeline into a GStreamer pipeline dynamically, depending on the current position:

Recently we finished the replacement of GNonLin with Non Linear Engine. This means the composition uses a master thread for setting up the pipeline, whereas before the old composition used to unlink/relink new pipelines from both the streaming thread and from the seeking thread and this was causing Deadlocks (“the other thousand”). Whatsmore, we previously had to have all the elements in the entire timeline available in the composition in the PAUSED state, which meant there were many—so many!—useless threads, created and waiting like sitting ducks; whereas elements are now created only when the pipeline needs them, and they are kept in the READY state until they are actually used by the pipeline.

Long live Non Linear Engine!

June 23, 2015

Setting up Supybot with the Bugzilla plugin

Supybot is an IRC bot, an application which can connect to a specific IRC channel and do stuff there. For example, with the Bugzilla plugin, Supybot can report on the channel whenever a new bug is filed, or if somebody mentions "bug 1234" in the conversation, it will print details about bug 1234.

Install supybot

First, you have to install Supybot. If you are using Arch Linux, get supybot from AUR, otherwise read the INSTALL file.

Create a supybot user on your system, or on a virtual machine where you want to run the bot.

groupadd --system supybot
useradd -m --system -g supybot supybot

Install the supybot Bugzilla plugin

If you want your bot to announce when new bugs are created, you need to set up an email account, register it on bugzilla and set it up so it gets mails when bugs for your project are created. For this go to Bugzilla -> Preferences -> Email Preferences and read the User Watching section!

Once you have the email account receiving emails from bugzilla, setup getmail on your machine so it downloads the messages from the email account to /var/mail/supybot.

touch /var/mail/supybot
chown supybot.supybot /var/mail/supybot
chmod g+w /var/mail/supybot
chmod o-rwx /var/mail/supybot
chown supybot.supybot /var/mail/supybot

Set the getmail job to download the messages using POP and to delete them from the server after retrieving them.

type = Mboxrd
path = /var/mail/supybot

verbose = 2
message_log = ~/.getmail/gmail.log

Now add yourself to the supybot group (so your getmail cronjob can write the bugzilla emails to /var/mail/supybot). For this to take effect the best option is to re-login!
usermod -a -G supybot YOUR_USERNAME

Add a crontab to your account (not supybot) to fetch the bugzilla mail every minute.

* * * * * getmail -d -q -r /path/to/your/getmail/config/file

Setup your bot

Next you have to create a config, and here it gets even more tricky. Unfortunately, most of the Supybot documentation is gone because the website is dead and only redirects to the sourceforge page of the project, where Supybot can be downloaded. You have to create a config using supybot-wizard:

mkdir /home/supybot/pitivi
cd /home/supybot/pitivi
# I suggest to act as an "advanced user" when the wizard asks you
# about what kind of user you are!
# Now see the conf file it created, feel free to rename it to bot.conf. ;)
ls -l *.conf

Copy the Supybot Bugzilla plugin to your setup. Unfortunately the original repository is broken, but you can get it from my Supybot Bugzilla repository.

cd /home/supybot/pitivi
mkdir plugins
cd plugins
bzr co bzr:// # Broken
git clone Bugzilla

Copy the bugzilla section from this sample config file to your bot.conf file. Or copy it from the pitivibot's bot.conf file below.

# Determines the bot's default nick.
# Default value: supybot
supybot.nick: pitivibot

# Determines what alternative nicks will be used if the primary nick
# (supybot.nick) isn't available. A %s in this nick is replaced by the
# value of supybot.nick when used. If no alternates are given, or if all
# are used, the supybot.nick will be perturbed appropriately until an
# unused nick is found.
# Default value: %s` %s_
supybot.nick.alternates: %s` %s_

# Determines the bot's ident string, if the server doesn't provide one
# by default.
# Default value: supybot
supybot.ident: supybot

# Determines the user the bot sends to the server. A standard user using
# the current version of the bot will be generated if this is left
# empty.
# Default value:
supybot.user: pitivibot

# Determines what networks the bot will connect to.
# Default value:
supybot.networks: freenode

# Determines what password will be used on freenode. Yes, we know that
# technically passwords are server-specific and not network-specific,
# but this is the best we can do right now.
# Default value:

# Determines what servers the bot will connect to for freenode. Each
# will be tried in order, wrapping back to the first when the cycle is
# completed.
# Default value:

# Determines what channels the bot will join only on freenode.
# Default value:
supybot.networks.freenode.channels: #pitivi

# Determines what key (if any) will be used to join the channel.
# Default value:

# Determines whether the bot will attempt to connect with SSL sockets to
# freenode.
# Default value: False
supybot.networks.freenode.ssl: False

# Determines how timestamps printed for human reading should be
# formatted. Refer to the Python documentation for the time module to
# see valid formatting characters for time formats.
# Default value: %I:%M %p, %B %d, %Y
supybot.reply.format.time: %H:%M %Y-%m-%d %Z

# Determines whether elapsed times will be given as "1 day, 2 hours, 3
# minutes, and 15 seconds" or as "1d 2h 3m 15s".
# Default value: False
supybot.reply.format.time.elapsed.short: True

# Determines the absolute maximum length of the bot's reply -- no reply
# will be passed through the bot with a length greater than this.
# Default value: 131072
supybot.reply.maximumLength: 131072

# Determines whether the bot will break up long messages into chunks and
# allow users to use the 'more' command to get the remaining chunks.
# Default value: True
supybot.reply.mores: True

# Determines what the maximum number of chunks (for use with the 'more'
# command) will be.
# Default value: 50
supybot.reply.mores.maximum: 50

# Determines how long individual chunks will be. If set to 0, uses our
# super-tweaked, get-the-most-out-of-an-individual-message default.
# Default value: 0
supybot.reply.mores.length: 0

# Determines how many mores will be sent instantly (i.e., without the
# use of the more command, immediately when they are formed). Defaults
# to 1, which means that a more command will be required for all but the
# first chunk.
# Default value: 1
supybot.reply.mores.instant: 1

# Determines whether the bot will send multi-message replies in a single
# message or in multiple messages. For safety purposes (so the bot is
# less likely to flood) it will normally send everything in a single
# message, using mores if necessary.
# Default value: True
supybot.reply.oneToOne: True

# Determines whether the bot will reply with an error message when it is
# addressed but not given a valid command. If this value is False, the
# bot will remain silent, as long as no other plugins override the
# normal behavior.
# Default value: True
supybot.reply.whenNotCommand: False

# Determines whether error messages that result from bugs in the bot
# will show a detailed error message (the uncaught exception) or a
# generic error message.
# Default value: False
supybot.reply.error.detailed: False

# Determines whether the bot will send error messages to users in
# private. You might want to do this in order to keep channel traffic to
# minimum. This can be used in combination with
# supybot.reply.error.withNotice.
# Default value: False
supybot.reply.error.inPrivate: False

# Determines whether the bot will send error messages to users via
# NOTICE instead of PRIVMSG. You might want to do this so users can
# ignore NOTICEs from the bot and not have to see error messages; or you
# might want to use it in combination with supybot.reply.errorInPrivate
# so private errors don't open a query window in most IRC clients.
# Default value: False
supybot.reply.error.withNotice: False

# Determines whether the bot will send an error message to users who
# attempt to call a command for which they do not have the necessary
# capability. You may wish to make this True if you don't want users to
# understand the underlying security system preventing them from running
# certain commands.
# Default value: False
supybot.reply.error.noCapability: False

# Determines whether the bot will reply privately when replying in a
# channel, rather than replying to the whole channel.
# Default value: False
supybot.reply.inPrivate: False

# Determines whether the bot will reply with a notice when replying in a
# channel, rather than replying with a privmsg as normal.
# Default value: False
supybot.reply.withNotice: False

# Determines whether the bot will reply with a notice when it is sending
# a private message, in order not to open a /query window in clients.
# This can be overridden by individual users via the user configuration
# variable reply.withNoticeWhenPrivate.
# Default value: False
supybot.reply.withNoticeWhenPrivate: False

# Determines whether the bot will always prefix the user's nick to its
# reply to that user's command.
# Default value: True
supybot.reply.withNickPrefix: False

# Determines whether the bot should attempt to reply to all messages
# even if they don't address it (either via its nick or a prefix
# character). If you set this to True, you almost certainly want to set
# supybot.reply.whenNotCommand to False.
# Default value: False
supybot.reply.whenNotAddressed: False

# Determines whether the bot will allow you to send channel-related
# commands outside of that channel. Sometimes people find it confusing
# if a channel-related command (like Filter.outfilter) changes the
# behavior of the channel but was sent outside the channel itself.
# Default value: False
supybot.reply.requireChannelCommandsToBeSentInChannel: False

# Supybot normally replies with the full help whenever a user misuses a
# command. If this value is set to True, the bot will only reply with
# the syntax of the command (the first line of the help) rather than the
# full help.
# Default value: False
supybot.reply.showSimpleSyntax: False

# Determines what prefix characters the bot will reply to. A prefix
# character is a single character that the bot will use to determine
# what messages are addressed to it; when there are no prefix characters
# set, it just uses its nick. Each character in this string is
# interpreted individually; you can have multiple prefix chars
# simultaneously, and if any one of them is used as a prefix the bot
# will assume it is being addressed.
# Default value:

# Determines what strings the bot will reply to when they are at the
# beginning of the message. Whereas prefix.chars can only be one
# character (although there can be many of them), this variable is a
# space-separated list of strings, so you can set something like '@@ ??'
# and the bot will reply when a message is prefixed by either @@ or ??.
# Default value:

# Determines whether the bot will reply when people address it by its
# nick, rather than with a prefix character.
# Default value: True
supybot.reply.whenAddressedBy.nick: False

# Determines whether the bot will reply when people address it by its
# nick at the end of the message, rather than at the beginning.
# Default value: False
supybot.reply.whenAddressedBy.nick.atEnd: False

# Determines what extra nicks the bot will always respond to when
# addressed by, even if its current nick is something else.
# Default value:

# Determines whether the bot will unidentify someone when that person
# changes his or her nick. Setting this to True will cause the bot to
# track such changes. It defaults to False for a little greater
# security.
# Default value: False
supybot.followIdentificationThroughNickChanges: False

# Determines whether the bot will always join a channel when it's
# invited. If this value is False, the bot will only join a channel if
# the user inviting it has the 'admin' capability (or if it's explicitly
# told to join the channel using the Admin.join command)
# Default value: False
supybot.alwaysJoinOnInvite: False

# Determines what message the bot replies with when a command succeeded.
# If this configuration variable is empty, no success message will be
# sent.
supybot.replies.success: The operation succeeded.

# Determines what error message the bot gives when it wants to be
# ambiguous.
supybot.replies.error: An error has occurred and has been logged. Please\
contact this bot's administrator for more\

# Determines what message the bot replies with when someone tries to use
# a command that requires being identified or having a password and
# neither credential is correct.
supybot.replies.incorrectAuthentication: Your hostmask doesn't match or your\
password is wrong.

# Determines what error message the bot replies with when someone tries
# to accessing some information on a user the bot doesn't know about.
supybot.replies.noUser: I can't find %s in my user database. If you didn't\
give a user name, then I might not know what your\
user is, and you'll need to identify before this\
command might work.

# Determines what error message the bot replies with when someone tries
# to do something that requires them to be registered but they're not
# currently recognized.
supybot.replies.notRegistered: You must be registered to use this command.\
If you are already registered, you must\
either identify (using the identify command)\
or add a hostmask matching your current\
hostmask (using the "hostmask add" command).

# Determines what error message is given when the bot is telling someone
# they aren't cool enough to use the command they tried to use.
supybot.replies.noCapability: You don't have the %s capability. If you think\
that you should have this capability, be sure\
that you are identified before trying again.\
The 'whoami' command can tell you if you're\

# Determines what generic error message is given when the bot is telling
# someone that they aren't cool enough to use the command they tried to
# use, and the author of the code calling errorNoCapability didn't
# provide an explicit capability for whatever reason.
supybot.replies.genericNoCapability: You're missing some capability you\
need. This could be because you\
actually possess the anti-capability\
for the capability that's required of\
you, or because the channel provides\
that anti-capability by default, or\
because the global capabilities include\
that anti-capability. Or, it could be\
because the channel or\
supybot.capabilities.default is set to\
False, meaning that no commands are\
allowed unless explicitly in your\
capabilities. Either way, you can't do\
what you want to do.

# Determines what error messages the bot sends to people who try to do
# things in a channel that really should be done in private.
supybot.replies.requiresPrivacy: That operation cannot be done in a channel.

# Determines what message the bot sends when it thinks you've
# encountered a bug that the developers don't know about.
supybot.replies.possibleBug: This may be a bug. If you think it is, please\
file a bug report at

# A floating point number of seconds to throttle snarfed URLs, in order
# to prevent loops between two bots snarfing the same URLs and having
# the snarfed URL in the output of the snarf message.
# Default value: 10.0
supybot.snarfThrottle: 10.0

# Determines the number of seconds between running the upkeep function
# that flushes (commits) open databases, collects garbage, and records
# some useful statistics at the debugging level.
# Default value: 3600
supybot.upkeepInterval: 3600

# Determines whether the bot will periodically flush data and
# configuration files to disk. Generally, the only time you'll want to
# set this to False is when you want to modify those configuration files
# by hand and don't want the bot to flush its current version over your
# modifications. Do note that if you change this to False inside the
# bot, your changes won't be flushed. To make this change permanent, you
# must edit the registry yourself.
# Default value: True
supybot.flush: True

# Determines what characters are valid for quoting arguments to commands
# in order to prevent them from being tokenized.
# Default value: "
supybot.commands.quotes: "

# Determines whether the bot will allow nested commands, which rule. You
# definitely should keep this on.
# Default value: True
supybot.commands.nested: True

# Determines what the maximum number of nested commands will be; users
# will receive an error if they attempt commands more nested than this.
# Default value: 10
supybot.commands.nested.maximum: 10

# Supybot allows you to specify what brackets are used for your nested
# commands. Valid sets of brackets include [],
, and {} (). [] has
# strong historical motivation, as well as being the brackets that don't
# require shift.
or () might be slightly superior because they cannot
# occur in a nick. If this string is empty, nested commands will not be
# allowed in this channel.
# Default value: []
supybot.commands.nested.brackets: []

# Supybot allows nested commands. Enabling this option will allow nested
# commands with a syntax similar to UNIX pipes, for example: 'bot: foo |
# bar'.
# Default value: False
supybot.commands.nested.pipeSyntax: False

# Determines what commands have default plugins set, and which plugins
# are set to be the default for each of those commands.
supybot.commands.defaultPlugins.addcapability: Admin
supybot.commands.defaultPlugins.capabilities: User
supybot.commands.defaultPlugins.disable: Owner
supybot.commands.defaultPlugins.enable: Owner Misc
supybot.commands.defaultPlugins.ignore: Admin

# Determines what plugins automatically get precedence over all other
# plugins when selecting a default plugin for a command. By default,
# this includes the standard loaded plugins. You probably shouldn't
# change this if you don't know what you're doing; if you do know what
# you're doing, then also know that this set is case-sensitive.
# Default value: Plugin Admin Misc User Owner Config Channel
supybot.commands.defaultPlugins.importantPlugins: Plugin Admin Misc User Owner Config Channel
supybot.commands.defaultPlugins.list: Misc
supybot.commands.defaultPlugins.reload: Owner
supybot.commands.defaultPlugins.removecapability: Admin
supybot.commands.defaultPlugins.unignore: Admin

# Determines what commands are currently disabled. Such commands will
# not appear in command lists, etc. They will appear not even to exist.
# Default value:

# Determines whether the bot will defend itself against command-
# flooding.
# Default value: True
supybot.abuse.flood.command: True

# Determines how many commands users are allowed per minute. If a user
# sends more than this many commands in any 60 second period, he or she
# will be ignored for supybot.abuse.flood.command.punishment seconds.
# Default value: 12
supybot.abuse.flood.command.maximum: 12

# Determines how many seconds the bot will ignore users who flood it
# with commands.
# Default value: 300
supybot.abuse.flood.command.punishment: 300

# Determines whether the bot will defend itself against invalid command-
# flooding.
# Default value: True
supybot.abuse.flood.command.invalid: True

# Determines how many invalid commands users are allowed per minute. If
# a user sends more than this many invalid commands in any 60 second
# period, he or she will be ignored for
# supybot.abuse.flood.command.invalid.punishment seconds. Typically,
# this value is lower than supybot.abuse.flood.command.maximum, since
# it's far less likely (and far more annoying) for users to flood with
# invalid commands than for them to flood with valid commands.
# Default value: 5
supybot.abuse.flood.command.invalid.maximum: 5

# Determines how many seconds the bot will ignore users who flood it
# with invalid commands. Typically, this value is higher than
# supybot.abuse.flood.command.punishment, since it's far less likely
# (and far more annoying) for users to flood witih invalid commands than
# for them to flood with valid commands.
# Default value: 600
supybot.abuse.flood.command.invalid.punishment: 600

# Determines the default length of time a driver should block waiting
# for input.
# Default value: 1.0
supybot.drivers.poll: 1.0

# Determines what driver module the bot will use. Socket, a simple
# driver based on timeout sockets, is used by default because it's
# simple and stable. Twisted is very stable and simple, and if you've
# got Twisted installed, is probably your best bet.
# Default value: default
supybot.drivers.module: default

# Determines the maximum time the bot will wait before attempting to
# reconnect to an IRC server. The bot may, of course, reconnect earlier
# if possible.
# Default value: 300.0
supybot.drivers.maxReconnectWait: 300.0

# Determines what directory configuration data is put into.
# Default value: conf
supybot.directories.conf: /home/supybot/pitivi/conf

# Determines what directory data is put into.
# Default value: data
### /home/supybot/pitivi/data

# Determines what directory temporary files are put into.
# Default value: tmp
### /home/supybot/pitivi/data/tmp

# Determines what directory backup data is put into.
# Default value: backup
supybot.directories.backup: /home/supybot/pitivi/backup

# Determines what directories the bot will look for plugins in. Accepts
# a comma-separated list of strings. This means that to add another
# directory, you can nest the former value and add a new one. E.g. you
# can say: bot: 'config supybot.directories.plugins [config
# supybot.directories.plugins], newPluginDirectory'.
# Default value:
supybot.directories.plugins: /home/supybot/pitivi/plugins

# Determines what directory the bot will store its logfiles in.
# Default value: logs
supybot.directories.log: /home/supybot/pitivi/logs

# Determines what plugins will be loaded.
# Default value:
supybot.plugins: Web Admin Misc Bugzilla User Owner Config Channel

# Determines whether this plugin is loaded by default.
supybot.plugins.Admin: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Admin.public: True

# Determines whether this plugin is loaded by default.
supybot.plugins.Bugzilla: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Bugzilla.public: True

# Determines whether the bug snarfer will be enabled, such that any
# Bugzilla URLs and bug ### seen in the channel will have their
# information reported into the channel.
# Default value: False
supybot.plugins.Bugzilla.bugSnarfer: True

# Users often say "bug XXX" several times in a row, in a channel. If
# "bug XXX" has been said in the last (this many) seconds, don't fetch
# its data again. If you change the value of this variable, you must
# reload this plugin for the change to take effect.
# Default value: 300
supybot.plugins.Bugzilla.bugSnarferTimeout: 300

# The fields to list when describing a bug, after the URL.
# Default value: bug_severity priority target_milestone assigned_to bug_status short_desc
supybot.plugins.Bugzilla.bugFormat: bug_severity priority target_milestone assigned_to bug_status short_desc

# The fields to list when describing an attachment after announcing a
# change to that attachment.
# Default value: type desc filename
supybot.plugins.Bugzilla.attachFormat: type desc filename

# How various messages should be formatted in terms of bold, colors,
# etc.

# When the plugin reports that something has changed on a bug, how
# should that string be formatted?
# Default value: teal
supybot.plugins.Bugzilla.format.change: teal

# When the plugin reports the details of an attachment, how should we
# format that string?
# Default value: green
supybot.plugins.Bugzilla.format.attachment: green

# When the plugin reports the details of a bug, how should we format
# that string?
# Default value: red
supybot.plugins.Bugzilla.format.bug: red

# The number of results to show when using the "query" command.
# Default value: 5
supybot.plugins.Bugzilla.queryResultLimit: 5

# A path to the mbox that we should be watching for bugmail.
# Default value:
supybot.plugins.Bugzilla.mbox: /var/mail/supybot

# How many seconds should we wait between polling the mbox?
# Default value: 10
supybot.plugins.Bugzilla.mboxPollTimeout: 10

# Various messages that can be re-formatted as you wish. If a message
# takes a format string, the available format variables are: product,
# component, bug_id, attach_id, and changer)

# What the bot will say when somebody adds a new attachment to a bug.
# Default value: %(changer)s added attachment %(attach_id)d to bug %(bug_id)d
supybot.plugins.Bugzilla.messages.newAttachment: %(changer)s added attachment %(attach_id)d to bug %(bug_id)d

# What the bot will say when a new bug is filed.
# Default value: New %(product)s bug %(bug_id)d filed by %(changer)s.
supybot.plugins.Bugzilla.messages.newBug: New %(product)s bug %(bug_id)d filed by %(changer)s.

# How should we describe it when somebody requests a flag without
# specifying a requestee? This should probably start with "from." It can
# also be entirely empty, if you want.
# Default value: from the wind
supybot.plugins.Bugzilla.messages.noRequestee: from the wind

# The various Bugzilla installations that have been created with the
# 'add' command.
# Default value:
supybot.plugins.Bugzilla.bugzillas: gnome

# Determines the URL to this Bugzilla installation. This must be
# identical to the urlbase (or sslbase) parameter used by the
# installation. (The url that shows up in emails.) It must end with a
# forward slash.
# Default value:

# Additional search terms in QuickSearch format, that will be added to
# every search done with "query" against this installation.
# Default value:

# Should *all* changes be reported to this channel?
# Default value: False
supybot.plugins.Bugzilla.bugzillas.gnome.watchedItems.all: False

# Whose changes should be reported to this channel?
# Default value:

# What components should be reported to this channel?
# Default value:

# What products should be reported to this channel?
# Default value:
supybot.plugins.Bugzilla.bugzillas.gnome.watchedItems.product: pitivi

# The names of fields, as they appear in bugmail, that should be
# reported to this channel.
# Default value: newBug, newAttach, Flags, Attachment Flags, Resolution, Product, Component
supybot.plugins.Bugzilla.bugzillas.gnome.reportedChanges: newBug

# Some Bugzilla installations have gdb stack traces in comments. If you
# turn this on, the bot will report some basic details of any trace that
# shows up in the comments of a new bug.
# Default value: False
### False

# Some functions are useless to report, from a stack trace. This
# contains a list of function names to skip over when reporting traces
# to the channel.
# Default value: __kernel_vsyscall raise abort ??
supybot.plugins.Bugzilla.bugzillas.gnome.traces.ignoreFunctions: __kernel_vsyscall raise abort ??

# How many stack frames should be reported from the crash?
# Default value: 5
supybot.plugins.Bugzilla.bugzillas.gnome.traces.frameLimit: 5

# If commands don't specify what installation to use, then which
# installation should we use?
# Default value:
supybot.plugins.Bugzilla.defaultBugzilla: gnome

# Determines whether this plugin is loaded by default.
supybot.plugins.Channel: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Channel.public: True

# Determines whether the bot will always try to rejoin a channel
# whenever it's kicked from the channel.
# Default value: True
supybot.plugins.Channel.alwaysRejoin: True

# Determines whether this plugin is loaded by default.
supybot.plugins.Config: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Config.public: True

# Determines whether this plugin is loaded by default.
supybot.plugins.Misc: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Misc.public: True

# Determines whether the bot will list private plugins with the list
# command if given the --private switch. If this is disabled, non-owner
# users should be unable to see what private plugins are loaded.
# Default value: True
supybot.plugins.Misc.listPrivatePlugins: False

# Determines the format string for timestamps in the Misc.last command.
# Refer to the Python documentation for the time module to see what
# formats are accepted. If you set this variable to the empty string,
# the timestamp will not be shown.
# Default value: [%H:%M:%S]
supybot.plugins.Misc.timestampFormat: [%H:%M:%S]

# Determines whether or not the timestamp will be included in the output
# of last when it is part of a nested command
# Default value: False
supybot.plugins.Misc.last.nested.includeTimestamp: False

# Determines whether or not the nick will be included in the output of
# last when it is part of a nested command
# Default value: False
supybot.plugins.Misc.last.nested.includeNick: False

# Determines whether this plugin is loaded by default.
supybot.plugins.Owner: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Owner.public: True

# Determines what quit message will be used by default. If the quit
# command is called without a quit message, this will be used. If this
# value is empty, the nick of the person giving the quit command will be
# used.
# Default value:

# Determines whether this plugin is loaded by default.
supybot.plugins.User: True

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.User.public: True

# Determines whether this plugin is loaded by default.
supybot.plugins.Web: False

# Determines whether this plugin is publicly visible.
# Default value: True
supybot.plugins.Web.public: True

# Determines whether the bot will output the HTML title of URLs it sees
# in the channel.
# Default value: False
supybot.plugins.Web.titleSnarfer: False

# Determines what URLs are to be snarfed and stored in the database in
# the channel; URLs matching the regexp given will not be snarfed. Give
# the empty string if you have no URLs that you'd like to exclude from
# being snarfed.
# Default value:

# Determines the maximum number of bytes the bot will download via the
# 'fetch' command in this plugin.
# Default value: 0
supybot.plugins.Web.fetch.maximum: 0

# Determines whether the bot will always load important plugins (Admin,
# Channel, Config, Misc, Owner, and User) regardless of what their
# configured state is. Generally, if these plugins are configured not to
# load, you didn't do it on purpose, and you still want them to load.
# Users who don't want to load these plugins are smart enough to change
# the value of this variable appropriately :)
# Default value: True
supybot.plugins.alwaysLoadImportant: True

# Determines what databases are available for use. If this value is not
# configured (that is, if its value is empty) then sane defaults will be
# provided.
# Default value: sqlite anydbm cdb flat pickle

# Determines what filename will be used for the users database. This
# file will go into the directory specified by the
# supybot.directories.conf variable.
# Default value: users.conf
supybot.databases.users.filename: users.conf

# Determines how long it takes identification to time out. If the value
# is less than or equal to zero, identification never times out.
# Default value: 0
supybot.databases.users.timeoutIdentification: 0

# Determines whether the bot will allow users to unregister their users.
# This can wreak havoc with already-existing databases, so by default we
# don't allow it. Enable this at your own risk. (Do also note that this
# does not prevent the owner of the bot from using the unregister
# command.)
# Default value: False
supybot.databases.users.allowUnregistration: False

# Determines what filename will be used for the ignores database. This
# file will go into the directory specified by the
# supybot.directories.conf variable.
# Default value: ignores.conf
supybot.databases.ignores.filename: ignores.conf

# Determines what filename will be used for the channels database. This
# file will go into the directory specified by the
# supybot.directories.conf variable.
# Default value: channels.conf
supybot.databases.channels.filename: channels.conf

# Determines whether database-based plugins that can be channel-specific
# will be so. This can be overridden by individual channels. Do note
# that the bot needs to be restarted immediately after changing this
# variable or your db plugins may not work for your channel; also note
# that you may wish to set
# appropriately if you
# wish to share a certain channel's databases globally.
# Default value: True
supybot.databases.plugins.channelSpecific: False

# Determines what channel global (non-channel-specific) databases will
# be considered a part of. This is helpful if you've been running
# channel-specific for awhile and want to turn the databases for your
# primary channel into global databases. If
# prevents linking,
# the current channel will be used. Do note that the bot needs to be
# restarted immediately after changing this variable or your db plugins
# may not work for your channel.
# Default value: #
### #

# Determines whether another channel's global (non-channel-specific)
# databases will be allowed to link to this channel's databases. Do note
# that the bot needs to be restarted immediately after changing this
# variable or your db plugins may not work for your channel.
# Default value: True
### True

# Determines whether CDB databases will be allowed as a database
# implementation.
# Default value: True
supybot.databases.types.cdb: True

# Determines how often CDB databases will have their modifications
# flushed to disk. When the number of modified records is greater than
# this part of the number of unmodified records, the database will be
# entirely flushed to disk.
# Default value: 0.5
supybot.databases.types.cdb.maximumModifications: 0.5

# Determines what will be used as the default banmask style.
# Default value: host user
supybot.protocols.irc.banmask: host user

# Determines whether the bot will strictly follow the RFC; currently
# this only affects what strings are considered to be nicks. If you're
# using a server or a network that requires you to message a nick such
# as then you you should set this to False.
# Default value: False
supybot.protocols.irc.strictRfc: False

# Determines what user modes the bot will request from the server when
# it first connects. Many people might choose +i; some networks allow
# +x, which indicates to the auth services on those networks that you
# should be given a fake host.
# Default value:

# Determines what vhost the bot will bind to before connecting to the
# IRC server.
# Default value:

# Determines how many old messages the bot will keep around in its
# history. Changing this variable will not take effect until the bot is
# restarted.
# Default value: 1000
supybot.protocols.irc.maxHistoryLength: 1000

# A floating point number of seconds to throttle queued messages -- that
# is, messages will not be sent faster than once per throttleTime
# seconds.
# Default value: 1.0
supybot.protocols.irc.throttleTime: 1.0

# Determines whether the bot will send PINGs to the server it's
# connected to in order to keep the connection alive and discover
# earlier when it breaks. Really, this option only exists for debugging
# purposes: you always should make it True unless you're testing some
# strange server issues.
# Default value: True
### True

# Determines the number of seconds between sending pings to the server,
# if pings are being sent to the server.
# Default value: 120
### 120

# Determines whether the bot will refuse duplicate messages to be queued
# for delivery to the server. This is a safety mechanism put in place to
# prevent plugins from sending the same message multiple times; most of
# the time it doesn't matter, unless you're doing certain kinds of
# plugin hacking.
# Default value: False
supybot.protocols.irc.queuing.duplicates: False

# Determines how many seconds must elapse between JOINs sent to the
# server.
# Default value: 0.0
supybot.protocols.irc.queuing.rateLimit.join: 0.0

# Determines how many bytes the bot will 'peek' at when looking through
# a URL for a doctype or title or something similar. It'll give up after
# it reads this many bytes, even if it hasn't found what it was looking
# for.
# Default value: 4096
supybot.protocols.http.peekSize: 4096

# Determines what proxy all HTTP requests should go through. The value
# should be of the form 'host:port'.
# Default value:

# Determines whether the bot will ignore unregistered users by default.
# Of course, that'll make it particularly hard for those users to
# register or identify with the bot, but that's your problem to solve.
# Default value: False
supybot.defaultIgnore: False

# A string that is the external IP of the bot. If this is the empty
# string, the bot will attempt to find out its IP dynamically (though
# sometimes that doesn't work, hence this variable).
# Default value:

# Determines what the default timeout for socket objects will be. This
# means that *all* sockets will timeout when this many seconds has gone
# by (unless otherwise modified by the author of the code that uses the
# sockets).
# Default value: 10
supybot.defaultSocketTimeout: 10

# Determines what file the bot should write its PID (Process ID) to, so
# you can kill it more easily. If it's left unset (as is the default)
# then no PID file will be written. A restart is required for changes to
# this variable to take effect.
# Default value:

# Determines whether the bot will automatically thread all commands.
# Default value: False
supybot.debug.threadAllCommands: False

# Determines whether the bot will automatically flush all flushers
# *very* often. Useful for debugging when you don't know what's breaking
# or when, but think that it might be logged.
# Default value: False
supybot.debug.flushVeryOften: False

# Determines what the bot's logging format will be. The relevant
# documentation on the available formattings is Python's documentation
# on its logging module.
# Default value: %(levelname)s %(asctime)s %(name)s %(message)s
supybot.log.format: %(levelname)s %(asctime)s %(name)s %(message)s

# Determines what the minimum priority level logged to file will be. Do
# note that this value does not affect the level logged to stdout; for
# that, you should set the value of supybot.log.stdout.level. Valid
# values are DEBUG, INFO, WARNING, ERROR, and CRITICAL, in order of
# increasing priority.
# Default value: INFO
supybot.log.level: INFO

# Determines the format string for timestamps in logfiles. Refer to the
# Python documentation for the time module to see what formats are
# accepted. If you set this variable to the empty string, times will be
# logged in a simple seconds-since-epoch format.
# Default value: %Y-%m-%dT%H:%M:%S
supybot.log.timestampFormat: %Y-%m-%dT%H:%M:%S

# Determines whether the bot will log to stdout.
# Default value: True
supybot.log.stdout: True

# Determines whether the bot's logs to stdout (if enabled) will be
# colorized with ANSI color.
# Default value: False
supybot.log.stdout.colorized: True

# Determines whether the bot will wrap its logs when they're output to
# stdout.
# Default value: True
supybot.log.stdout.wrap: False

# Determines what the bot's logging format will be. The relevant
# documentation on the available formattings is Python's documentation
# on its logging module.
# Default value: %(levelname)s %(asctime)s %(message)s
supybot.log.stdout.format: %(levelname)s %(asctime)s %(message)s

# Determines what the minimum priority level logged will be. Valid
# values are DEBUG, INFO, WARNING, ERROR, and CRITICAL, in order of
# increasing priority.
# Default value: INFO
supybot.log.stdout.level: DEBUG

# Determines whether the bot will separate plugin logs into their own
# individual logfiles.
# Default value: False
supybot.log.plugins.individualLogfiles: False

# Determines what the bot's logging format will be. The relevant
# documentation on the available formattings is Python's documentation
# on its logging module.
# Default value: %(levelname)s %(asctime)s %(message)s
supybot.log.plugins.format: %(levelname)s %(asctime)s %(message)s

# These are the capabilities that are given to everyone by default. If
# they are normal capabilities, then the user will have to have the
# appropriate anti-capability if you want to override these
# capabilities; if they are anti-capabilities, then the user will have
# to have the actual capability to override these capabilities. See
# docs/CAPABILITIES if you don't understand why these default to what
# they do.
# Default value: -owner -admin -trusted
supybot.capabilities: -owner -admin -trusted

# Determines whether the bot by default will allow users to have a
# capability. If this is disabled, a user must explicitly have the
# capability for whatever command he wishes to run.
# Default value: True
supybot.capabilities.default: False

Make it dance

Now start your bot from the command line. This way you can see the debug log messages, in case you need to figure out why it does not work.

sudo -u supybot supybot /home/supybot/pitivi/bot.conf

Finally, create /lib/systemd/system/supybot.service to have it started automatically.
Description=Pitivi IRC bot

ExecStart=/usr/bin/supybot /home/supybot/pitivi/bot.conf


Remember to start it and enable it to start automatically.
systemctl start supybot
systemctl enable supybot

Alternatively, create a file in /etc/init/ so Supybot is started automatically when the system starts. I probably copied the file below from somewhere, but I don't remember from where.

# This IRC bot serves #pitivi.
description "Pitivi IRC bot"

# I got this from mysql.conf, you might want to have a look
# at other files in /etc/init/ and copy a section which
# looks appropriate. Basically it should start the daemon
# after the network is started.
start on (net-device-up
and local-filesystems
and runlevel [2345])
stop on runlevel [016]

# Restart if it dies unexpectedly. Should not happen.

# Make sure the binary exists.
# It's recommended you install supybot from the current git
# HEAD, because no features are being worked on, and it
# should be stable:
# In this case, the binary is in /usr/local/bin/supybot.
# This may differ if you are using, the package included in
# your Linux distribution, for example.
pre-start script
test -x /usr/local/bin/supybot || { stop; exit 0; }
end script

# Output to the console whatever it outputs.
console output

# Run the bot with the specified config file.
# The bot does not need to run as a daemon, unless
# there are other jobs depending on its sucessful start,
# for example. If there are, you should add "expect fork",
# and specify --daemon to the command line, and hope that
# it works, because:
# "One needs to be very careful with the expect stanza
# to avoid confusing Upstart: the program must fork in
# precisely the expected way." ion
# To create the supybot system user and system group, and
# add yourself to the group so you can easily edit files
# run:
# addgroup --system supybot
# adduser --system --ingroup supybot supybot
exec sudo -u supybot /usr/local/bin/supybot /home/supybot/pitivi/bot.conf

Congratulations! Send me an email and tell me how happy you are that you have your bot. ;)

June 11, 2015

The War Against Deadlocks, part 1: The story of our new thread-safe mixing elements implementation

Let me tell you of a story that was lost and forgotten amidst Pitivi’s development battlegrounds last fall, a manuscript that I recovered from a Moldy Tome in a stony field. According to my historical data, the original author was a certain “Dorian Leger”, a French messenger that went missing from the vicinity of Paris.

Moldy TomeThe Moldy Tome as I found it

I am taking the liberty of altering fairly substantially this manuscript to clarify some parts while restoring its intent and style according to the historical context. It will serve as the first part of an epic tale (the second part is yet to be written, it will come in the next blog post, though it will probably have a more “modern” writing style), about our war against deadlocks, vile creatures that have been threatening the stability of our application for much too long. Technically, we’ve always been at war with EastasiaDeadlocks; you can see that even in the noble title of our 0.13.2 release, from a time when a different squad of maintainers roamed this land.

Previous maintainers fighting the FomorsPrevious maintainers fighting the Fomors, in the 0.8-0.10 GSt Era.

Without further ado, here is my transcription of the report:

Paris, le vingt-huit septembre, MMXIV

Dear supporters of the Video Editing Liberation Front,

Over the last month and a half, we have made major strides debugging and rewriting important backend code that Pitivi depends on. At the edge of the land of Pitivi, we are approaching the 0.94 milestone, which we plan on liberating in the coming weeks. I have been discussing with sieur Duponchelle to enquire about a particular piece of work the Company has been preparing for that purpose. He said, “We have torn out a large chunk of bug-ridden code in GStreamer and replaced it with a brand new videomixing element that we can finally show with pride and confidence. It will be a tremendous help in our battle against the Deadlocks; hopefully, it will give us stable and bug-free seeking in the timeline at last.”

Indeed, I have heard tales of previous Pitivi versions consistently crashing when seeking in a section of cross-faded (overlapped) clips. In other words, when we tried to select a frame that contained a cross-fade from one clip to another, Pitivi would freeze up and need to be put by the sword. Needless to say, this bug was killing not only the user experience, but also the morale of our troops, and needed to be dealt with as swiftly and efficiently as possible.

The technical problem behind this nuisance was a powerful piece of equipment in the GStreamer artillery: the GstElement videomixer. This contraption was trying to deal with threads other elements were throwing at it, which was by design extremely complex and error-prone—to the point where some have said it to be the work of the Devil itself.

Ming Dynasty eruptor proto-cannon

When we inspected the machine, we found the diagram above. Transcription of the odd scriptures in that diagram leads to the following interpretation of how it operated:

“To make this machine worketh, thou wilt receive buffers from all them sinkpads in different threads. Therefore, thou wilt wait for all thy pads to get a buffer to decide to mix & push the result on thy srcpad; hence thou shall be pushing buffers from the thread on which thee hath received thy last buffer. Eke, make sure not to stand in front of the machine when operating it.” — Dante, son of Sparda

Multithreading, if you recall your scholarship with the monks of Shaolin, is a difficult art to master. It allows running multimedia processing tasks in the background and enables several tasks to be executed simultaneously. A multi-threaded approach is essential to us, but also requires tedious management of variables shared by different threads (these variable usually describe audio data and video pixelization, in the case of the GstElement videomixer machine). As simultaneous threads often work on the same variables, the backend developer, proficient in the ancient C language, needs to ensure these threads do not simultaneously edit a variable, and the developer must carefully manage how threads give each other the signal to edit a variable.

shaolin tiger style

In the case of the strange machine that was causing those problems, we destroyed it with fire and rebuilt it with simplicity and harmony in mind. I cannot tell for sure, but I have been told that over ten thousand lines of ancient codes were rewritten through the exquisite art of multithreading kung fu. The new videomixer machine now has the srcpad running its own thread, and we aggregate and push buffers on the srcpad from that thread. This technique makes us much stronger against the Deadlocks.

As you have certainly seen for yourselves, previous Pitivi versions—particularly due to the mixing elements in GStreamer—were plagued with bugs causing threads to wait for each other indefinitely. To make this easier to imagine, let’s take a modern analogy: the previous videomixer implementation looked like a city full of cars at stop-sign intersections, waiting for the each other to go, causing endless traffic jams behind them. The good news is, after rewriting over 10,000 lines of code, the stop-signs were replaced by a much simpler and reliable system in 0.94, which means our videomixing element is now thread-friendly and ‘bug-free’. This required a complete rework of our mixing stack (by writing a new baseclass to substitute to collectpads2). It was quite an involved process.

We’re quite happy with what we have achieved there, but the Deadlocks are not so easily vanquished, and the story doesn’t end there. The rest of the manuscript is fairly short and consisted mostly of predictions for events that have now occurred since then, which I will be covering in the next blog post when I find more time, as it requires further analysis and expansion.

Thank you for reading, commenting and sharing! This blog post is part of a série of articles tracking progress made with work related to the 2014 Pitivi fundraiser. Researching and writing quality articles takes a lot of time, so please be patient and enjoy the ride! 😉
  1. An update from the 2014 summer battlefront
  2. The 0.94 release
  3. The War Against Deadlocks, part 1: The story of our new thread-safe mixing elements reimplementation
  4. The War Against Deadlocks, part 2: GNonLin's reincarnation
  5. The 0.95 release, the GTK+ timeline and sink
  6. Measuring quality/reliability through time (clarifying what gst-validate is)
  7. Our all-in-one binaries building infrastructure, and why it matters
  8. Samples, “scenario” files and you: how you can help us reproduce (almost) any bug very easily
  9. The 1.0 release and closure of the fundraiser

May 07, 2015

President’s Report — The State of the GNOME Foundation

As I hinted in my retrospective in February, 2014 has been crazy busy on a personal level. Let’s now take a look at 2014-2015 from a GNOME perspective.

When I offered my candidacy for the GNOME Foundation‘s Board of Directors in May last year, I knew that there would be plenty of issues to tackle if elected. As I was elected president afterwards, I was aware that I was getting into a demanding role that would not only test my resolve but also make use of my ability to set a clear direction and keep us moving forward through tough times. But even if someone tries to describe what’s involved in all this, it remains difficult to truly grasp the amount of work involved before you’ve experienced it yourself.

For one thing, I can say that running a branding & management consulting business at the same time as you’re steering an established public charity like the GNOME Foundation is definitely not easy.

2015-03-cal-blurredPictured: my calendar during the month of March

Throughout the year, I went through moments of great joy and periods of deep exhaustion where I cursed Firefox’s bug 60455 — working everyday until 1-2 AM (and waking up 5-6 hours later), for months on end, to get things done. Since 2015, my GTG todo list has consistently been at 4x my normal “healthy” quota. For example, in March, I was at 190 actionable tasks and a total of 520 tasks. Whew! So, in the name of sanity, I had to slow down some of my business activities and withdrew almost all of my involvement in the Pitivi project this term (I’ll be writing a news update blog post soon, I promise!).

I did not compromise on my involvement with the GNOME Foundation because I felt a huge responsibility towards my teammates and towards the Foundation Membership who elected us. Most of the board members, in addition to their daily work, underwent significant personal challenges during the year: relocating, career changes, family matters, all sorts of things that can affect one’s life. And yet, with the limited bandwidth we had, the Board soldiered on and accomplished many feats. I consider myself lucky to have had such a competent and deeply caring team of people to work through one of the busiest years GNOME has had yet!

2014-2015 GNOME Foundation board

What also keeps me motivated is the incredible strength of our community, the technical excellence of our platform and the fundamental need for a GNOME “desktop” (or GNOME OS) to exist. More than ever, we need Free and affordable computing for everyone. If proprietary vendors, DRM, the industry shift towards “renting” (rather than owning) software and the Snowden revelations taught us anything over the years, it’s that we need to be the truly free system that people can trust for all their computing needs, online and offline. Many have their heads in the clouds, but we need to keep our feet on the ground and be the bridge between the sky and earth—the safe base where people will come back to.

The Space Elevator, by Dusty CrosleyThe Space Elevator, by Dusty Crosley

For that reason, I’m pretty excited by our friends at Endless who are shipping a radically different desktop computer running GNOME and a set of applications that will run offline, designed to make the lives of millions (billions!) of people easier in the developing world. I’m proud of our little cousin, elementary, for shipping a new version of their OS—even as an established project with lots of momentum, we can still learn a lot from what they’re doing, and we certainly appreciate their involvement in our shared technologies. Fedora Workstation, with its refined focus, is something else I’m pretty happy about. With sandboxing, OSTree and Builder in the works, I’m looking forward to GNOME OS becoming a reality. We need something rock solid and for which we can sculpt the user experience from the ground up, something which also serves as a reference and entrypoint for new contributors willing to create applications for the exciting GNOME ecosystem.

We’ve made major strides towards creating a stable and refined platform over the past few years. We have our work cut out for us in a number of areas and I look forward to us tackling them as a community. For example, one thing I’m passionate about is having a “bulletproof” OS that can handle the most demanding creative workloads, without the user needing to worry about the system’s resource usage. I should be able to have Firefox (or Web/Epiphany) running at the same time as GIMP, Inkscape and Pitivi without an exabyte of RAM or having the kernel/graphics subsystem go unresponsive due to one application hoarding resources. I know we can do better in this space. With our unparalleled ability to oversee changes through the whole stack and upcoming technologies like containers & sandboxing, we have the potential to be the most advanced OS in the world—we just need to seize this opportunity.

There are also new fields of computing that we are poised to explore as a free desktop: virtual reality—bringing a new meaning to the term “virtual desktops”—is certainly the next big step in “office computing” (including productivity and creative work, entertainment, etc.—not just gaming). We should investigate VR as the next big evolution of the desktop. Imagine getting rid of the limitations imposed by computer multi-head monitor frames…

ghost in the shell VR

We should tackle these things one step at a time, together. It takes many small efforts to steer a ship this big, and the Foundation is there to support the community every step of the way.

Here is a snapshot of what the Foundation’s Board of Directors were up to this year:

  • Dealing with over 3700 emails
  • Held 25+ regular board meetings, on the phone or in person
    • In addition to those, we held a few “special meetings” for topics like adboard outreach and ED search to drain the swamp. Therefore, in practice, we have been meeting more often than the already fast-paced bi-weekly meetings schedule.
  • Exchanged over 24,000 lines of IRC discussion within the board
  • Resolved the cash-flow problem (a.k.a. financial/success crisis) that occurred in the spring of 2014. We collected on every single outstanding invoice for OPW and will be announcing more about this soon.
  • Dealt with two very serious complaints brought to our attention — one of them is not fully resolved yet, but we’re working on it.
  • Represented GNOME at various conferences (GUADEC, SFD, GSoC Mentors Summit, OSCON, FOSDEM, LGM, GNOME.Asia, LinuxCon North America, LinuxCon Europe, and probably a bunch of others I’m forgetting).
  • Negotiated with Groupon for six months before the trademark opposition filing deadline. As we reached the deadline and could wait no longer, we prepared and launched a public fundraiser and awareness campaign. This initiative worked above all expectations, with more than 100K USD raised within a day and Groupon immediately capitulating upon seeing the incredible public support we were able to muster. We got coverage in a number of media outlets, including the World Trademark Review magazine. We hope that our experience stands for the proposition that companies must respect free software communities, and we’re already seeing our situation held up as an example to support that.
  • Reached out to current (and past) advisory board members on the phone or in person.
  • Sought new sponsorship opportunities
  • Set up a kanban system to keep track of the “big picture” of long-running projects and action items.
  • Started the hunt for an Executive Director, including forming a search & hiring committee
  • Reviewed & approved budgets and reimbursements for various events
  • Reviewed & approved various trademark use requests
  • Started work on prospecting new sources of funding for the GNOME sysadmin role
  • Provided advice on fundraising for the Telder font
  • Signed two legal agreements with the Software Freedom Conservancy for the transfer of Outreachy — more news on this later
  • Administered OPW (including legal and financial aspects), until the migration to Outreachy under the SFC was completed
  • Worked on various aspects of codes of conduct
  • Initiated work on a Privacy policy
  • Provided support for GNOME conferences, including GUADEC, GNOME.Asia, the Boston Summit and the West Coast Summit
  • Signed a deal with the WHS for handling funds in Europe — more news on this later
  • Various ongoing financial and legal tasks
  • Transferred the ownership of various assets (including domain names such as
  • Responded to various press or events organization inquiries, phone calls, etc.
  • Apologized to people for not moving fast enough on some matters ;)

I can tell you, like anyone who has worked on a board of directors without an Executive Director for the entire term, that I have developed a tremendous amount of respect and patience towards the work done by each volunteer and team in the GNOME community. There is so much that needs to be done to keep the GNOME Project running, it would not be possible without your help. Thank you, everyone!

November 03, 2014

Tricks or Tracebacks? Pitivi 0.94 is here

Dear werepenguins, we’re thrilled to announce the immediate availability of Pitivi 0.94! This is the fourth release for the new version of our video editor based on GES, the GStreamer Editing Services library. Take a look at my previous blog post to understand in what context 0.94 has been brewing. This is mainly a maintenance release, but it does pack a few interesting improvements & features in addition to the bug fixes.

The first thing you will notice is that the main toolbar, menubar and titlebar have been replaced by a unified GTK HeaderBar, saving a ton of precious vertical space and making better use of the horizontal space. Once you try it, you can’t go back. There is beauty in the equilibrium it has now, compared to the previously clunky and unbalanced layout:

pitivi 0.94 headerbar comparison 1Pitivi 0.93 on the left, 0.94 on the right

The combined screenshot above allows you to get the “complete picture” of how this change affects the main window, but it’s hard to get a sense of scale and it does not really do justice to the awesomeness of client-side decorations like the GTK HeaderBar. So here’s a simplified version where all the “wasted space” is highlighted in red:

pitivi 0.94 headerbar comparison 2Pitivi 0.93 above, 0.94 below

Pretty rad, huh?

Beyond that eye-popping novelty, many distro/setup-dependent startup crashes have been investigated and fixed:

  • Various Linux distributions have started shipping a broken version of CoGL in recent months, which led to crashes. Technically this is a bug in the CoGL library/packaging, but we found out that the functions we were calling in that particular case were not needed for Pitivi, so we dropped our use of those broken CoGL APIs. Problem solved.
  • People running Pitivi outside of GNOME Shell were seeing crashes due to Clutter GStreamer video output, so we ported the viewer widget to use GStreamer’s new GL video output (glimagesink) instead of the ClutterSink. We had to fix various bugs in GStreamer’s glimagesink to raise it to the quality we needed, and our fixes have been integrated in GStreamer 1.4 (this is why we depend on that version). The GL image sink is expected to be a more future-proof solution.
  • We found issues related to gobject introspection or the overrides provided by gst-python. Again, make sure you have version 1.4 for things to work properly.
  • On avant-garde Linux distributions, you would get a TypeError traceback (“unsupported operand type(s) for /: ‘int’ and ‘NoneType”) preventing startup, which we investigated as bug 735529. This is now fixed in Pitivi.

We also have a collection of bug fixes to the way we handle the various resizeable & detachable components of the main window:

  • The default positioning of UI components (when starting from a fresh install) has been improved to be balanced properly
  • Undocked window components do not shift position on startup anymore
  • Docked window components do not shift position on startup anymore, when the window is not maximized. When the window is maximized, the issue remains (your help to investigate this problem is very much welcome, see bug 723061)

The title editor’s UI has been simplified and works much more reliably:

pitivi 0.94 title editor


  • Undo/redo should be globally working again; please file specific bug reports for the parts that don’t.
  • Pitivi has been ported to Python 3
  • The user manual is now up to date with the state of the new Pitivi series
  • Educational infobars throughout the UI have been tweaked to make their colors less intrusive
  • Various other fixes as usual. Testing and providing detailed reports for issues you encounter certainly helps!
  • There’s more. Find out in the release notes for 0.94!

This release is meant to be the last release based on our current “buggy stack”; indeed, as I mentioned in my previous status update, the next release (0.95) will run on top of a refined and incredibly more robust backend thanks to the work that Mathieu and Thibault have been doing to replace GNonLin by NLE (the new non-linear engine for GES) and fixing videomixing issues.

We recommend all 0.91/0.92/0.93 users to upgrade to this release. Until this trickles down into distributions, you can download our all-in-one bundle and try out 0.94, right here and now. Enjoy!

October 04, 2014

An update from the Pitivi 2014 summer battlefront

Hello gentle readers! You may have been wondering what has been going on since the 0.93 release and the Pitivi fundraising campaign. There are a few reasons why we’ve been quiet on the blogging side this summer:

  • Mathieu and Thibault have been working hard to bring us towards “1.0 quality”, improving and stabilizing various parts of GStreamer to make the backend of Pitivi more reliable (more details on this further below). They preferred to write code rather than spending their time doing marketing/fundraising. This is understandable, it is a better use of our scarce specialized resources.
  • Personally, I have been juggling with many obligations (my daily business, preparing for the conferences season, serving on the board of the GNOME Foundation, and Life in General), which left me with pretty much no time or energy to do development on marketing-related activities on Pitivi, just enough to participate in some discussions and help with administration/co-mentorship a bit. I did not have time to research blogging material about what others were doing, hence the lack of status updates in recent times.

Now that I finally have a little bit of time on my hands, I will provide you with the overdue high-level status update from the trenches.

Summer Wars. That’s totally how coding happens in the real world.

GUADEC, status of the 2014 fundraiser

For the curious among you, my account of GUADEC 2014 is here. Among the multiple presentations I gave there, my main talk was about Pitivi. I touched upon the status of the fundraiser in my talk; however, the recordings are not yet available, so I’ll share some select notes on this topic here:

  • Personally, I’ve always thought that, to be worth it, we should raise 200 thousand dollars per year, minimum (you’ll be able to hear the explanation for this belief of mine in the economic context I presented in my talk).
  • For this fundraiser, we aimed for a “modest” minimum target of 35k and an “optimistic” target of 100k. So, much less than 200k.
  • Early on after the campaign launch, we had to scale back on hopes of hitting the “optimistic” target and set 35k as the new “maximum” we could expect, as it became clear from the trend that we would not reach 100k.
  • Eventually, the fundraiser reached its plateau, at approximately 19K €, a little bit over half of our base target.

We had a flexible funding scheme, a great website and fundraising approach, we have the reputation and the skills to deliver, we had one of the best run campaigns out there (we actually got praised on that)… and yet, it seems that was not enough. shrugAfter four months spent preparing and curating our fundraiser, at one point we had to reassess our priorities and focus on “more urgent” things than full-time fundraising: improving code, earning a living, etc. Pushing further would have meant many more months of energy-draining marketing work which, as mentioned in the introduction of this post, was not feasible or productive for us at that point in time. Our friends at MediaGoblin certainly succeeded, in big part through their amazing focus and persistence (Chris Webber spent three months writing substantial motivational blog posts twice a week and applying for grants to achieve his goal. Think about it: fourteen blog articles!).

Okay so now you’re thinking, “But you still got a bit of money, so what have you guys done with that?”. We’ve accomplished some great QA/bugfixing work, just not as fast or as extensively as we’d like to. Pitivi 1.0 will happen but, short of seeing a large amount of donations, it will take more time to reach that goal (unless people step up with patches :).

What Mathieu & Thibault have been up to

For starters, they set up a continuous integration and multi-platform build system for quality assurance.

Then they worked on the GStreamer video mixer, basically doing a complete rework of our mixing stack, and made the beast thread-safe… this is supposed to fix a ton of deadlocks related to videomixing that were killing our user experience by causing frequent freezes. They are preparing a blog post specifically on this topic, but in the meantime you can see some gory details by looking at these commits they landed in GStreamer so far (more are on the way, pending review):

Then they pretty much rewrote all of GNonLin with a different, simpler design, and integrated it directly into GES under a new name: “NLE” (Non Linear Engine):


The only part that survived from GNonLin, as far as I know, is the tree data structure generation. So, with “NLE” in GES, deadlocks from GNonLin should be a thing of the past; seeking around should be much more reliable and not cause freezes like it used to. This is still a major chunk of code: it represents around six thousand lines of new code in GES. Work is ongoing in this branch, expected to be completed and merged sometime in October, so I’m waiting to see what comes out of it in practice.

This is in addition to crazy bugs like bug 736896 and our regular bug fixing operations. See also the Pitivi tracker bug for GTK3, introspection and GST1 bugs and the Pitivi tracker bug for Python3 port issues.

The way forward

Now that a big chunk of the hardcore backend work has been done, Thibault and Mathieu will be able to focus on Pitivi (the UI) again. Here is the rough plan for coming months:

  1. “Scenarios” in Pitivi: each action from the user would be serialized (saved) as GstValidateScenario actions, allowing us to easily reproduce issues and bugs that you encounter.
  2. Go over the list of all reported Pitivi bugs and fix a crapton of them!
  3. At some point, we will call upon you to help us with extensive testing (including reporting the bugs and discussing with us to investigate them). We will then continue fixing bugs, release often and make sure we reach the quality you can expect of a 1.0 release.

More news to come

Thank you for reading, commenting and sharing! This blog post is part of a série of articles tracking progress made with work related to the 2014 Pitivi fundraiser. Researching and writing quality articles takes a lot of time, so please be patient and enjoy the ride! 😉
  1. An update from the 2014 summer battlefront
  2. The 0.94 release
  3. The War Against Deadlocks, part 1: The story of our new thread-safe mixing elements reimplementation
  4. The War Against Deadlocks, part 2: GNonLin's reincarnation
  5. The 0.95 release, the GTK+ timeline and sink
  6. Measuring quality/reliability through time (clarifying what gst-validate is)
  7. Our all-in-one binaries building infrastructure, and why it matters
  8. Samples, “scenario” files and you: how you can help us reproduce (almost) any bug very easily
  9. The 1.0 release and closure of the fundraiser

September 11, 2014

Recent Changes in Pitivi User Documentation

I feel like the basic (re)writing of Pitivi user docs is done so I thought I should take a while to describe the current state of the docs and point to further tasks that need to be done. When I started, nekohayo gave me his to-do list that he kept specifically for docs, which helped me to get going. For the first commit, the choice was clear: add Pitivi’s license to the manual’s license page. As close to a one-liner as you can get. Soon, I got into the flow and as a result, the user manual now looks a little more complete. Of course there are some remaining issues I haven’t had time to cover yet. These are mostly tracked in bugzilla.

Also, screenshots should be updated in the manual, but I was postponing this intentionally for two reasons. First, there might be some slight UI changes on the way to 1.0 and second, it is not a big deal since the gnome docs team recommends (because of the difficulties this poses for docs translation) to use only one screenshot — that of the main window overview. So the screenshot is just waiting for the right time to be switched.

More interestingly, I have an experimental branch containing a troubleshooting page. I know that the Pitivi developers work hard to clear all issues that would possibly need troubleshooting, but in the meantime, I thought this page could provide some guidance. You can look at the branch in my Github repository. Any thoughts or comments are appreciated!

August 29, 2014

Wow, 7 years….

Originally post to Collabora co-workers:

7 years since starting the Collabora Multimedia adventure,
7 years of challenges, struggles, and proving we could tackle them
7 years of success, pushing FOSS in more and more areas (I can still hear Christian say “de facto” !)
7 years of friendship, jokes, rants,
7 years of being challenged to outperform one self,
7 years of realizing you were working with the smartest and brightest engineers out there,
7 years of pushing the wtf-meter all the way to 11, yet translating that in a politically correct fashion to the clients
7 years of life …
7 years … that will never be forgotten, thanks to all of you

It’s never easy … but it’s time for me to take a long overdue break, see what other exciting things life has to offer, and start a new chapter.

So today is my last day at Collabora. I’ve decided that after 17 years of non-stop study and work (i.e. since I last took more than 2 weeks vacation in a row), it was time to take a break.

What’s next ? Tackling that insane todo-list one compiles over time but never gets to tackle :). Some hacking and GStreamer (obviously), some other life related stuff, traveling, visiting friends, exploring new technologies and fields I haven’t had time to look deeper into until now, maybe do some part-time teaching, write more articles and blogposts, take on some freelance work here and there, … But essentially, be in full control of what I’m doing for the next 6-12 months.

Who knows what will happen. It’s both scary … and tremendously exciting :)

PS 1: While my position at Collabora as Multimedia Domain Lead has already been taken over by the insane(ly amazing) Olivier Crete (“tester” from GStreamer fame), Collabora is looking for more Multimedia engineers. If you’re up for the challenge, contact them :)

PS 2. wtf-meter :

PS 3. My non-Collabora email address is <my nickname>@<my nickname> dot com

August 28, 2014

GStreamer continuous testing (Part 1)

History so far

For the past 6-9 months, as part of some of the tasks I’ve been handling at Collabora, I’ve been working on setting up a continuous build and testing system for GStreamer. For those who’ve been following GStreamer for long enough, you might remember we had a buildbot instance back around 2005-2006, which continuously built and ran checks on every commit. And when it failed, it would also notify the developers on IRC (in more or less polite terms) that they’d broken the build.

The result was that master (sorry, I mean main, we were using CVS back then) was guaranteed to always be in a buildable state and tests always succeeded. Great, no regressions, no surprises.

At some point in time (around 2007 I think ?) the buildbot was no longer used/maintained… And eventually subtle issues crept in, you wouldn’t be guaranteed checkouts always compile, tests eventually broke, you’d need to track what introduced a regression (git bisect makes that easier, but avoiding it in the first place is even better), etc…

What to test

Fast-forward to 2013, after talking so much about it, it was time to bring back such a system in place. Quite a few things have changed since:

  • There’s a lot more code. In 2005, when 0.10 was released, the GStreamer project was around 400kLOC. We’re now around 1.5MLOC ! And I’m not even taking into account all the dependency code we use in cerbero, the system for building binary SDK releases.
  • There are more usages that we didn’t have back then. New modules (rtsp-server, editing-services, orc now under the GStreamer project umbrella, ..)
  • We provide binary releases for Windows, MacOSX, iOS, Android, …

The problems to tackle were “What do we test ? How do we spot regressions ? How to make it as useful as possible to developers ?”.

In order for a CI system to be useful, you want to limit the Signal-To-Noise ratio as much as possible. Just enabling a massive bunch of tests/use-cases with millions of things to fix is totally useless. Not only is it depressing to see millions of failed tests, but also you can’t spot regressions easily and essentially people don’t care anymore (it’s just noise). You want the system to become a simple boolean (Either everything passes, or something failed. And if it failed, it was because of that last commit(s)). In order to cope with that, you gradually activate/add items to do and check. The bare minimum was essentially testing whether all of GStreamer compiled on a standard linux setup. That serves as a reference point. If someone breaks the build, it becomes useful, you’ve spotted a regression, you can fix it. As time goes by, you start adding other steps and builds (make check passes on gstreamer core, activate that, passes on gst-plugins-base, activate that, cerbero builds fully/cleanly on debian, activate that, etc…).

The other important part is that you want to know as quickly as possible whether a regression was introduced. If you need to wait 3 hours for the CI system to report a regression … that person will have gone to sleep or be taken up by something else. If you know within 10-15mins, then it’s still fresh in their head, they are most likely still online, and you can correct the issue as quickly as possible.

Finally, what do we test ? GStreamer has gotten huge. in that sentence GStreamer is actually not just one module, but a whole collection (GStreamer core, gst-plugins*, but also ORC, gst-rtsp-server, gnonlin, gst-editing-services, ….). Whatever we produce for every release … must be covered. So this now includes the binary releases (formerly from, but which are handled by the GStreamer project itself since 1.x). So we also need to make sure nothing breaks on all the platforms we target (Linux, Android, OSX, iOS, Windows, …).

To summarize

  1. CI system must be set-up progressively (to detect regressions)
  2. CI system must be fast (so person who introduced the regression can fix it ASAP)
  3. CI system must cover all our offering (including cerbero binary builds)

The result is here (yes, I know, we’re working on fixing the certificates once it moves to the final namespace).

How this was implemented, and what challenges were encountered and handled will be covered in a next post.

August 07, 2014

Retour de GUADEC, conspirations

As expected, GUADEC in Strasbourg was a terrific event. Huge props to the local organizing team who managed to make things work regardless of last minute curve balls, such as the venue changing or the video recording team (and their equipment) not being able to attend due to visa restrictions. I went with Alexandre Franke to pick up recording equipment only half an hour before the opening session on the first day, and manned the cameras sporadically, but was glad that other volunteers were able to fill the gaps as I was running all over the place.

Since I am independent this year (I now have my own business, as some of you might have seen from my unusual laptop sticker), I came to GUADEC thinking I would allow myself to really relax for a change:

“This is great! Besides my daily two-hours of contract work obligation, and my Pitivi talk, and my two days of GNOME Foundation board meetings, I’m a free bird cat! I’ll be able to focus on watching talks, discuss at length with everybody, and get back to making technical contributing to Pitivi this week! \(• ◡ •)/”

grump cat nope grayscale

I had a few surprises:

  • Pinpoint decided to go on strike (hey, this is France after all!) and not display half of my images, so I had to waste ridiculous amounts of time redoing my Pitivi presentation entirely with LibreOffice Impress.
  • I was asked to do the opening session of the conference.
  • And later asked to open the Teams Reports session by presenting an overview of the Foundation’s activities for the year prior to my election.
  • And then to do the closing session as well (in which my theatrical talents were revealed by way of an outrageous accent and legendary repartee).

All on short notice. No sweat.

On the night of the event at the Snooker, I hopped into Thibault’s car (the Pitivimobile; five Pitivi hackers were in it) and we tried getting from his flat to the Snooker bar. We never made it to the Snooker. Instead, we spent 2.5 hours going through every street in Strasbourg, which is quite hilarious—thanks to Thibault and Mathieu’s wonderful sense of orientation, we had a free city tour and a very entertaining experience!

The picnic event was nice and popular. Thankfully, mosquitoes focused on Europeans and left Canoodians like me alone.

The Pitivi & GStreamer hackfest was productive, lots of stabilization/bugfixing work done by Mathieu and Thibault as part of their work enabled by the fundraiser. Lubosz worked on Windows component builds because he has a gluttony for pain.

As part of my pro-bono/FOSS-related projects at idéemarque, a few months ago I spent time rethinking the contents of the GStreamer website, as well as turning those contents into a working website for demonstration and planning purposes. During the hackfest at GUADEC, I therefore spent a few hours discussing with Tim, Sebastian and Edward about those contents, the target audience, intended structure, etc. Eventually, as time allows, we’ll get to the real implementation soonish.

2014-07-31Some whiteboard notes from the discussion

Unfortunately, in the half day that was left before my return trip, I couldn’t get much done on Pitivi itself asides from some light triaging and testing.

The scheduled talks were great. I was glad that there were only two tracks so that I wouldn’t miss too many of them… Except I still ended up missing most of them as I dealt with last minute issues all the time, so I’ll end up having to watch the recordings anyway! There’s over 100 GB of raw recordings, so let’s be patient toward those who will have the heroic duty of processing them for publishing.

A hero appears. Photo by Jakub SteinerPhoto by Jakub Steiner

I really liked that the venue was right into the heart of the city rather than on the outskirts. Strasbourg is a very pedestrian & bike-friendly city (in case you hadn’t realized from the Pitivimobile story). All the accomodation, restaurants and public transit were close by.

I was very happy to meet with a ton of people I wanted to see again, discuss issues that mattered to me and gather many insights along the way.

In the closing session, I was quite shocked by the unveiling of the Swedish Conspiracy. However, when you start looking more closely at the matter, I think some facts are difficult to overlook indeed:

Pictured: the Italo-Swedish conspiracyCoincidence? I think not.

All in all, this year’s GUADEC felt like a more modest and informal event compared to years past, while still retaining what makes it GUADEC: great topics, great people, positive energy and one of the most welcoming communities I know.

gnome sponsored badge shadow

July 28, 2014


Well hello there, dear Internet.

So yes, it’s been quite some time since the last blogpost. A lot has been going on, but that will be for future blogposts.

Currently at GUADEC 2014 in Strasbourg, France. Lots of interesting talks and people around.

Quite a few discussions with several people regarding future GStreamer improvements (1.4.0 is freshly out, we need to prepare 1.6 already). I’ll most likely be concentrating on the whole QA and CI side of things (more builds, make them clearer, make them do more), plan how to do nightly/weekly releases (yes, finally, I kid you not !). We also have a plan to make it faster/easier/possible for end-users (non-technical ones) to get GStreamer in their hands. More on that soon (unless Sebastian blogs about it first).

If you want to come hack on GStreamer and Pitivi, or discuss with the various contributors, there’s a Hackfest taking place at GUADEC from Wednesday to Friday. More info at

July 02, 2014

Venez nombreux à GUADEC!

Pour la première fois depuis quatorze ans, la conférence GUADEC fait son retour en France. Je vous encourage à venir nombreux à cet événement qui se tiendra à Strasbourg durant la dernière semaine de Juillet. Je dois traverser l’Atlantique (à la nage), prendre plusieurs avions et autobus pour y aller, alors pas d’excuses pour ceux situés à moins de 6000 km!

“GUADEC, ça a un intérêt pour quelqu’un qui n’est pas un développeur?”

La majorité des présentations (voir le programme qui sera publié sous peu) est à la portée du grand public avec un penchant geek, du moment que vous ayiez un fort intérêt/curiosité pour les technologies impliquées. On n’y retrouve habituellement pas Gaspard le boulanger ou Amélie la chirurgienne, mais tous sont les bienvenus. Après tout, GUADEC signifie “GNOME Users and Developers European Conference”!

GUADEC 2013 interns lightning talks, by Ana Rey

(photo par Ana Rey)

Les présentateurs axent souvent leur présentation autour des avancées récentes de leur logiciel, le design et l’expérience utilisateur, la direction générale d’un projet donné, etc. Bien sûr, plusieurs sujets restent à teneur assez technique, mais je crois que ceux qui lisent Planet Libre, Planet GNOME ou Linux FR sont déjà assez à l’affut pour comprendre le contenu. L’événement étant une conférence internationale, il faut toutefois avoir une compréhension correcte de l’anglais puisque c’est la langue utilisée lors des présentations.

Outre les présentations magistrales, il y a aussi les hackfests informels et sessions BoFs (“birds of a feather”), où des petits groupes se forment autour de thématiques particulières. Par exemple, il y a traditionnellement un hackfest pour Pitivi en présence des développeurs de GStreamer, étudiants GSoC et autres membres de la communauté intéressés. Amenez votre ordinateur et votre bonne humeur!

Bref, GUADEC reste beaucoup plus “accessible” aux non-devs que le GNOME Summit, ce dernier étant un événement très technique, plus proche d’un méga-hackfest.

“Que faire en tant que non-développeur?”

  • Rencontrer les contributeurs qu’on ne connaissait que de nom depuis des années, que ce soit dans les corridors ou dans les événements (généralement il y a au moins une ou deux soirées organisées).
  • Écouter des présentations en personne, poser des questions ou débattre.
  • Pourchasser nos développeurs préférés et discuter de nos bugs favoris. Pour reproduire un bug complexe à reproduire, ou simplement pour faire en sorte que le développeur se penche sur la question en investiguant en temps réel, il n’y a rien de mieux.
  • Discuter poliment de design sans avoir à écrire des pavés ou risquer des malentendus à cause du manque richesse des interactions textuelles.
  • Jouer le rôle de reporter et faire de la couverture médiatique de l’événement.
  • Rencontrer de nouveaux contributeurs, surtout les étudiants GSoC.
  • Participer aux sessions BoF (“birds of a feather”), notamment Le Pitivi Hackfest 2014.
  • Affronter Bastien Nocera au foot.

J’espère vous voir nombreux à cet événement incontournable!

June 23, 2014

June development update

Good news everyone !

This is the first blog post of a series of updates about our latest development efforts in GStreamer / gst-editing-services / Pitivi.

This post’s focus will be on MPEG transport stream, a format now nearly twenty years old, originally developed and still widely used for and by the broadcasting industry. In the mid-2000s, some people decided it would be a great idea to use this format in camcorders, stuffed a rather useless timestamp in there for good measure and started to ship AVCHD camcorders like it was the greatest thing since sliced bread.

It was not. See, most modern video codecs such as h264 rely on the notion of keyframes: to compress video streams as much as possible, most frames are encoded as their difference with the previous frame, we call these frames delta units. Sparsely distributed in the encoded stream are keyframes. These frames can be decoded without any reference to past frames, and when trying to seek in such a stream, decoding has to start from a keyframe and progress through all the delta units up to the requested frame.

Video editing implies accurate seeking, for example if you only want to include the 10 last frames of a 2-hour clip, decoding the whole file to obtain these few frames would be a pointless waste of time.

Failing to start decoding from a keyframe when seeking creates artefacts, garbled frames : the decoder is missing information to decode the delta unit, tries to provide a frame nevertheless and fails in doing so, until the next keyframe has been reached. Containers that are readily usable for editing contain information about the location of keyframes, in one form or another. This is not the case of MPEG TS, of which AVCHD is a subset. Locating the keyframes thus becomes a rather involved process, as one needs to parse the video streams in order to do so.

Backtracking to the introduction of this post, good news everyone ! We just did that, and here is a before / after video to demonstrate our changes. We can now ensure full support of AVCHD, enjoy😀

The next two posts will be respectively focused on our refactoring of our video / audio mixing stack, and our ongoing work on gnonlin, our non-linear editing engine.

A quick Pitivi status update for June 2014

I have been extremely busy in the past few months and thus have not been able to spend much time at all on Pitivi, but here’s a quick status update about the work of others in case you missed it:

  • In follow-up to our initial look at this summer’s GSoC projects for Pitivi:
  • Mathieu and Thibault have been hard at work to bring editing-ready MPEG-TS support for GStreamer, so you can finally edit those quirky AVCHD camcorder videos in Pitivi. Learn more about what they did in this blog post. The official fix, due for GStreamer 1.4, comes as part of bug #675132. For a historical sense of scale, see also this meta-bug on Launchpad and GStreamer bug #550634.
  • We will be at GUADEC. As per tradition, we will have a week-long Pitivi hackfest after the core presentations days. Do not hesitate to come hang around and get involved!

I will start preparing my GUADEC Pitivi talk soon. If there are topics or questions you would like to see covered, feel free to leave a comment to let me know.

June 19, 2014

Hi, ImageSequenceSrc!

Hello guys. I’ve written an element in gst-plugins-bad which I called as GstImageSequenceSrc. It works very similar to GstMultiFileSrc, but there are some differences.

Differences with GstMultiFileSrc.

Handles a list of filenames instead of a printf pattern as GstMultiFileSrc does.
* Having a list of filenames is useful because you can set the filenames you want,
in the order you want. For example, you can add more filenames or sort the list.
* There are two ways to create this list:
    a) Setting a location propertie. This value could look like:

  1. ’/some/folder/with/images/ or .’
  2. ’/a/path/img.jpg,/other/path/img2.jpg’ or ‘img1.png,img2.png’
  3. ’/a/path/*.JPEG or *.png’

    b) Setting the filename-list (GList) directly.

* Creates an “imagesequence://” protocol which allows the playbin to play this element. It handles a 'fake’ uri but it is useful finally.

gst-launch-1.0 playbin uri=“imagesequencesrc:///some/path/*.jpg?framerate=20/1&loop=1”

* It “detects” the mimetype of the images. You only have to worry about the framerate.
* It calculates the duration.

Things to improve:

* Seeking: it seeks to the wrong image sometimes (actually, after many seeks).
* The way duration is calculated.

PD: stormer, the guy who hangs on #gstreamer, was telling me to support png *and* jpeg files (both at the same time) but I don’t see a usecase.

You can see the most-stable version of this element in

The develop branch in (currently it is the same):

June 16, 2014

Transforming Video on the GPU

OpenGL is very suitable for calculating transformations like rotation, scale and translation. Since the video will end up on one rectangular plane, the vertex shader only needs to transform 4 vertices (or 5 with GL_TRIANGLE_STRIP) and map the texture to it. This is a piece of cake for the GPU, since it was designed to do that with many many more vertices, so the performance bottleneck will be uploading the video frame into GPU memory and downloading it again.

The transformations

GStreamer already provides some separate plugins that are basically suitable for doing one of these transformations.


videomixer: The videomixer does translation of the video with the xpos and ypos properties.

frei0r-filter-scale0tilt: The frei0r plugin is very slow, but it has the advantage of doing scale and tilt (translate) in one plugin. This is why i used it in my 2011 GSoC. It also provides a “clip” propery for cropping the video.


rotate: The rotate element is able to rotate the video, but it has to be applied after the other transformations, unless you want borders.

Screenshot from 2014-06-16 17:54:44


videoscale: The videoscale element is able to resize the video, but has to be applied after the translation. Additionally it resizes the whole canvas, so it’s also not perfect.

frei0r-filter-scale0tilt: This plugin is able to scale the video, and leave the cansas size as it is. It’s disadvantage is being very slow.

So we have some plugins that do transformation in GStreamer, but you can see that using them together is quite impossible and also slow. But how slow?

Let’s see how the performance of gltransformation compares to the GStreamer CPU transformation plugins.

Benchmark time

All the commands are measured with “time”. The tests were done on the nouveau driver, using MESA as OpenGL implementation. All GPUs should have simmilar results, since not really much is calculated on them. The bottleneck should be the upload.

Pure video generation

gst-launch-1.0 videotestsrc num-buffers=10000 ! fakesink

CPU 3.259s

gst-launch-1.0 gltestsrc num-buffers=10000 ! fakesink

OpenGL 1.168s

Cool the gltestsrc seem to run faster than the classical videotestsrc. But we are not uploading real video to the GPU! This is cheating! Don’t worry, we will do real world tests with files soon.

Rotating the test source

gst-launch-1.0 videotestsrc num-buffers=10000 ! rotate angle=1.1 ! fakesink

CPU 10.158s

gst-launch-1.0 gltestsrc num-buffers=10000 ! gltransformation zrotation=1.1 ! fakesink

OpenGL 4.856s

Oh cool, we’re as twice as fast in OpenGL. This is without uploading the video to the GPU though.

Rotating a video file

In this test we will rotate a HD video file with a duration of 45 seconds. I’m replacing only the sink with fakesink. Note that the CPU rotation needs  videoconverts.

gst-launch-1.0 filesrc location=/home/bmonkey/workspace/ges/data/hd/fluidsimulation.mp4 ! decodebin ! videoconvert ! rotate angle=1.1 ! videoconvert ! fakesink

CPU 17.121s

gst-launch-1.0 filesrc location=/home/bmonkey/workspace/ges/data/hd/fluidsimulation.mp4 ! decodebin ! gltransformation zrotation=1.1 ! fakesink

OpenGL 11.074s

Even with uploading the video to the GPU, we’re still faster!

Doing all 3 operations

Ok, now lets see how we perform in doing translation, scale and rotation. Note that the CPU pipeline does contain the problems described earlier.

gst-launch-1.0 videomixer sink_0::ypos=540 name=mix ! videoconvert ! fakesink filesrc location=/home/bmonkey/workspace/ges/data/hd/fluidsimulation.mp4 ! decodebin ! videoconvert ! rotate angle=1.1 ! videoscale ! video/x-raw, width=150 ! mix.

CPU 17.117s

gst-launch-1.0 filesrc location=/home/bmonkey/workspace/ges/data/hd/fluidsimulation.mp4 ! decodebin ! gltransformation zrotation=1.1 xtranslation=2.0 yscale=2.0 ! fakesink

OpenGL 9.465s

No surprise, it’s still faster and even correct.


Let’s be unfair and benchmark the frei0r plugin. There is one advantage, that it can do translation and scale correctly, but rotation can only be applied at the end. So no rotation at different pivot points is possible.

gst-launch-1.0 filesrc location=/home/bmonkey/workspace/ges/data/hd/fluidsimulation.mp4 ! decodebin ! videoconvert ! rotate angle=1.1 ! frei0r-filter-scale0tilt scale-x=0.9 tilt-x=0.5 ! fakesink

CPU 35.227s

Damn, that is horribly slow.

The gltransformation plugin is up to 3 times faster than that!


The gltransformation plugin does all 3 transformations together in a correct fashion and is fast in addition. Furthermore threedimensional transformations are possible, like rotating around the X axis or translating in Z. If you want, you can even use orthographic projection.

I also want to thank ystreet00 for helping me to get into the world of the GStreamer OpenGL plugins.

To run the test yourself, check out my patch for gst-plugins-bad:

Also don’t forget to use my python testing script:


gltransformation utilizes ebassi’s new graphene library, which implements linear algebra calculations needed for new world OpenGL without the fixed function pipeline.

Alternatives worth mentioning for C++ are QtMatrix4x4 and of course g-truc’s glm. These are not usable with GStreamer, and I was very happy that there was a GLib alternative.

After writing some tests and ebassi’s wonderful and quick help, Graphene was ready for usage with GStreamer!

Implementation in Pitivi

To make this transformation usable in Pitivi, we need some transformation interface. The last one I did was rendered in Cairo. Mathieu managed to get this rendered with the ClutterSink, but using GStreamer OpenGL plugins with the clutter sink is currently impossible. The solution will either be to extend the glvideosink to draw an interface over it or to make the clutter sink working with the OpenGL plugins. But I am rather not a fan of the clutter sink, since it introduced problems to Pitivi.

May 27, 2014

GstVideoOverlay Gtk+ OpenGL Sink Example in Python 3

I often forget how this exactly works, so here a minimalist example, translated from the C example in gst-plguns-bad.

Please note that this currently only works in X11, since the XID is needed.

You can exchange the sinks and sources. For example videotestsrc and xvimagesink.

Working with the Clutter sink requires a litte more work.

May 01, 2014

GSoC 2014 projects for Pitivi: transformation, chroma keying, image sequences

Thanks to GNOME, we will be able to get some reinforcements for Pitivi this summer.

We’re very pleased to have Lubosz Sarnecki making a comeback! In 2011 he implemented the cairo-based clip transformation (zoom/resize/crop) feature in the viewer. Lubosz is quite experienced with OpenGL, Blender and GStreamer, as you can see on his blog  and the variety of projects he contributes to.

lubosz working on the transformation UI in 2011Lubosz working on Pitivi at the 2011 Desktop Summit

This year, his project is:

  1. Evaluate the need for an OpenGL-based Ken Burns effect in GStreamer, vs an approach combining the CPU-based transformation plugins (videocrop, videoscale, videorotate and videomixer).
  2. Resurrect and extend our clip transformation user interface in Pitivi, to support rotation and animatable properties.
  3. Implement a color picker and custom chroma keying UI.

We’re also introducing Fabian Orccon as a GSoC student this year. His project will be to implement a user interface for handling image sequences (timelapses, stopmotion animation, output from Blender, etc.) as regular video clips in Pitivi. This is a fair amount of UI work, with possibly some work directly in GStreamer to improve the MultiFile element in gst-plugins-good. Depending on the remaining available time, he may also tackle bug fixing and implementing various features like copy-pasting clips. You can read Fabian’s initial blog post with mockups of how the image sequence UI/workflow could look like.

April 25, 2014

How would you like Pitivi image-sequence feature look?

Hello! I’m Fabián Orccón. I’ve been accepted to Google Summer of Code 2014 for GNOME with Pitivi. My project consists on adding an image-sequence feature to Pitivi. The usecases could be creating stop-motion films or a 2D animation for example.
The idea of this feature came to my mind when I wanted to film a homemade stop-motion movie with my sister. I had Ubuntu, and by that time Pitivi was the video-editing tool by default. I realized that Pitivi doesn’t have this feature implemented, and I wanted to do it.
I’m not the expert in the arts of cinematography. I was talking with Pitivi people and Bassam Kurdali, director of the first open movie, about how Pitivi could handle this feature. After mixing and organizing ideas I have this mockup. It is just a draft; I don’t know if I’m missing something.

I would like you to tell me how would you like this feature should work. Your opinion as user is so important. Pitivi wants to be the best option for you!


Download | svg |

April 21, 2014

gst-validate: A suite of tools to run integration tests for GStreamer

Collabora ltd. has been developing a tool that allows GStreamer developers to check that the GstElements they write behave the way they are supposed to: GstValidate. The tool was started first to provide plug-ins developers with a tool to check that they use the framework the proper way. Since the beginning, it has been available in gst-devtools, a gst module where we collect a set of tools to facilitate GStreamer development and usage.

Well, what is it about?

The GstValidateMonitor

Basically gst-validate allows us to monitor everything that is happening inside a GstPipeline. For example if you want to check that every component of a pipeline is properly behaving, you can create a GstValidatePipelineMonitor that will track that pipeline. Then each time a GstElement is added to the pipeline, a GstValidateElementMonitor will be instantiated and start tracking that element. Then when a GstPad is added to that GstElement a GstValidatePadMonitor will be monitoring that pad.

This monitoring logic allows us to check that what those elements do respect some rules GStreamer components have to follow so all the elements of a pipeline can properly interact together. For example, a GstValidatePadMonitor will make sure that if we receive a GstSegment from upstream, an equivalent segment is sent downstream before any buffer gets out. You can find the whole list of tests currently implemented here.

The GstValidateRunner

Then there is an issue reporting system so that each issue found during the execution of the pipeline is reported with as much details as possible so that users understand what the detected misbehaviour is about and can fix it efficiently.

In term of code the only thing to do in order to get a pipeline monitored is:

main (int argc, gchar ** argv)
 GstElement *pipeline;
 GstValidateRunner *runner;
 GstValidateMonitor *monitor;

 gboolean ret = 0;

 /* Initialize GStreamer and GstValidate */
 gst_init (&argc, &argv);
 gst_validate_init ();

 /* Create the pipeline and make sure it is
  * monitored */
 pipeline = gst_pipeline_new (
 runner = gst_validate_runner_new ();
 monitor = gst_validate_monitor_factory_create (
     GST_OBJECT (pipeline),

 /* HERE you can do anything you want with that
  * monitored pipeline */

 /* Now print the errors on stdout.
  * The return value of that function
  * is != 0 if if critical errors occured
  * during the execution of the pipeline */
 ret = gst_validate_runner_printf (runner);

 /* Cleanup */
 gst_object_unref (pipeline);
 gst_object_unref (monitor);
 gst_object_unref (runner);

 return ret;

The result of gst_validate_runner_printf will look something like:

issue : buffer is out of the segment range Detected on theoradec0.srcpad at 0:00:00.096556426
Details : buffer is out of segment and shouldn't be pushed. Timestamp: 0:00:25.000 - duration: 0:00:00.040 Range: 0:00:00.000 - 0:00:04.520
Description : buffer being pushed is out of the current segment's start-stop  range. Meaning it is going to be discarded downstream without any use

Here we can see that an issue occurred on the src pad of theoradec as it outputted a buffer that was not inside the segment it last pushed. This is an interesting piece of information and clearly shows an error in the element. (Note: This issue does not actually exist)

How should it be used?

GstValidate command line tools

In order to make gst-validate usage simple, we created command line tools that allow plugin developers test there elements in many use cases from a high level perspective.

The gst-validate pipeline launcher

This is a command line pipeline launcher similar to gst-launch. That tool uses the gst-launch pipeline description syntax and make sure that the pipeline is monitored and that the users will have all the reported information from the GstValidate infrastructure. As you can expect, you can monitor the playback of a media file using playbin as follow:

gst-validate-1.0 playbin uri=file:///.../file.ogg

You will then be able to see all the issues GstValidate found.

The gst-validate-transcoding tool

A command line tool allowing to test media files transcoding with a straight forward syntax. You can for example transcode any media file to vorbis vp8 in webm doing:

    -o 'video/webm:video/x-vp8:audio/x-vorbis'

It will report what issues happened during the execution of that pipeline.

The gst-validate-media-check tool

A command line tool checking that media files discovering works properly with gst-discoverer. Basically it needs a reference text file containing valid information about a media file (which can be generated with the same tool) and then it will be able to check that those informations correspond to what is reported by gst-discoverer over new runs.  For example, given that we have a valid reference.media_info file, we can run:

  --expected-results reference.media_info

That will then output found errors if any and return an exist code different from 0 if an error was found.


As you can notice, those tools let us test static pipelines execution and not that the pipeline reacts properly during execution of actions from the end user such as seeking, or changing the pipeline state, etc… In order to make that possible and easy to use we introduced the concept of scenarios.

A scenario is a set of actions to be executed on the monitored pipeline serialized in a text file. An  action (GstValidateAction) is just a function call executed at a precise time (usually based on the playback position of the pipeline).

An example of scenario:

# Just some metadatas describing the scenario
# The format is the GstStructure serialization 
# synthax
description, seek=true, duration=3.0

# When the pipeline reaches 1.0 second of
# playback it launches an accurate flushing
# seek to 10.0 seconds
seek, playback_time=1.0, start=10.0, 

# Send EOS to the pipeline
# so it stops and the application
# knows about it.
eos, playback_time=12.0

You can find more examples of scenarios here


This looks all right but shouldn’t those tests be executed automatically on a large number of samples and with the various existing scenarios? This is where gst-validate-launcher comes into play. It is basically a python application that launches the tools described above with the proper parameters. It then monitors them, check their results and serializes those results into a junit xml file (more formatter could obviously be implemented). That tools is pretty simple and it is only a matter of setting the media samples to run the tests on and set what scenarios you want to run.

Where is it used?

GStreamer Editing Services

As part of the GStreamer Editing Services project, I have made sure that ges-launch (a command line tool that launches timelines, video editing projects etc…) works with GstValidate, if compiled against it. This means that we can launch scenarios and test GES sharing the same infrastructure as the rest of GStreamer. It is also very interesting to be able to monitor dynamic pipeline (within GES the GstPipeline changes very dynamically) to discover elements misbehavior in that stressful use case. For the time being we do not have many GES specific GstValidateActions implemented, but we will implement more as needed (mostly implementing timeline edition actions, ie. moving clips around the timeline, changing effect properties, etc…) As part of the Pitvi fundraiser, we are also investigating how to serialize users action in Pitivi so that we could easily reproduce users issues outside of the application (and thus outside the python interpreter).

The GStreamer jenkins integration server

On the GStreamer continuous integration server, we are running gst-validate-launcher on a set of media sample in major formats after (almost) each commit on any of the component of the GStreamer stack. This is just the beginning and we are slowly adding more tests there making sure they pass and tracking regressions.

A lot of work has been done around that tool. We still need to clean up some part, review the few APIs we have, and a particular effort as to be made around the documentation. But now that good basis are there, we should just keep adding more tests to detect regressions in GStreamer as soon as possible. If you are interested in using that tool please come talk to us in #gstreamer on freenode!

April 14, 2014

First delivery of the pitivi fundraiser: universal daily bundles for Linux

The Pitivi community is very happy to announce the availability of easy to use, distro-independent Linux bundles to test latest version of the application. This eliminates dependency problems and allows quicker testing cycles. Our entire stack is bundled, so the only requirement is glibc ≥ 2.13.

Simply Download the bundle and run it!

This is the first delivery of the Pitivi Fundraiser—as you can see, we are already well on our way to deliver what has been promised in our detailed planning. You can have a look at what is happening with the “daily build” bundles on on our Jenkins instance (main server hosting donated by Collabora—thanks!).

To build the bundles we use Cerbero, which is the build and packaging system used by Collabora and Fluendo to construct the GStreamer SDK, and is also used by the GStreamer community to deliver GStreamer 1.x binaries for Android, iOS, Mac OS X and Windows. It is a very useful and well-designed technology, which will allow us to easily create packages for Windows and Mac OS X in the future.

This does not only apply to us, of course: work that has been made for creating Linux distro bundles allows anyone to easily create bundles for their applications with Cerbero. This has not been merged just yet, but that should happen quite soon. If you want to bundle your app using Cerbero, do not hesitate to ask us, even if it should already be really straight forward!

We raised half of the amount we are targeting for the Pitivi fundraising campaign, and we are in very good shape to be able to deliver everything on time. We need your help to reach that target.

Please donate now to make sure we will be able to provide the community with the great video editing app it deserves!

April 13, 2014

How to play a video using GES?

Hello. I want to show you an example of a command-line video player using GES. This program is very simple and my purpose is you learn the basis. I paste the enterily code here if you just want to read the code.

from gi.repository import Gtk
from gi.repository import GES
from gi.repository import Gst
from gi.repository import GObject

import signal

video_path = "/home/cfoch/Videos/samples/big_buck_bunny_1080p_stereo.ogg"

def handle_sigint(sig, frame):
    print "Bye!"

def busMessageCb(unused_bus, message):
    if message.type == Gst.MessageType.EOS:
        print "EOS: The End"

def duration_querier(pipeline):
    print pipeline.query_position(Gst.Format.TIME)
    return True

if __name__ == "__main__":

    video_uri = "file://" + video_path

    timeline = GES.Timeline.new_audio_video()
    layer = timeline.append_layer()

    asset = GES.UriClipAsset.request_sync(video_uri)
    clip = layer.add_asset(asset, 0, 0, asset.get_duration(), GES.TrackType.UNKNOWN)


    pipeline = GES.Pipeline()


    bus = pipeline.get_bus()
    bus.connect("message", busMessageCb)
    GObject.timeout_add(300, duration_querier, pipeline)

    signal.signal(signal.SIGINT, handle_sigint)


We’re going to start checking these lines.


We always need to use these lines to initialize GES. And you have to follow this order: initialize Gst before GES. If you change the order of these lines you program won’t work.

The next important line is

    timeline = GES.Timeline.new_audio_video()

With this line we create a Timeline. I understand the timeline as the general container. It will contain all the elements necessary to play the (edited) video or audio we want. A timeline contains GESVideoTracks and/or GESAudioTracks.

For example, if we want to play a video (with sound), our Timeline will contain both, a GESVideoTrack and a GESAudioTrack. If we want to play our favorite song, the timeline will contain only a GESAudioTrack.

In this case, this line is creating a GESTimeline adding to it a GESVideoTrack and a GESAudioTrack. It is a shortcut to it:

    videotrack =
    audiotrack =
    timeline =

The Timeline not only contains tracks, but also it contains many GESLayer. Our program will contain an only one GESLayer. But a Timeline is a stack of layers. The most-top layer will have the major priority. In the default case, the priority is given by 0. But… why do we need a GESLayer? Here we’ll add our clips, our effects, transitions. So, a GESLayer is another container. We not only create a GESLayer with this following line, but also we append the created layer to our timeline:

    layer = timeline.append_layer()

What it is a kind of confusing to me is the GESAsset. I found them as an abstract idea of information of the video or audio file for example we will use. However, a GESAsset is not only limited to audio and video. It can have information about an effect or about a GESVideoTrack/GESAudioTrack.

In this case we’ll take advantage of the method request_sync GESUriClipAsset which allow us to create a GESAsset from a real file located in our computer, for example from a ‘video.ogv’. This method gets information like the duration of the video.

    asset = GES.UriClipAsset.request_sync(video_uri)

The following line will generate the clip from the asset and add it to the layer we’ve created before.

    clip = layer.add_asset(asset, 0, 0, asset.get_duration(), GES.TrackType.UNKNOWN)

And To apply our changes…


To be able to display our video on the screen we need the GESPipeline. The GESPipeline allow us to play or render the result of our work, the result of our timeline. So a pipeline needs to be linked to a timeline.

    pipeline = GES.Pipeline()

By default, the state of the pipeline is NULL. However, we can change this state to PLAYING or RENDER. When its state is in PLAYING the pipeline will display the result in the screen. If the state is RENDER it will 'export’ the result of our work in an out_file.ogv video, for example. We will set the state or mode of the pipeline in PLAYING because we want only to play the video.


If we remove lines bewtween 43 and 48 lines, and we execute the program, we can see the video playing. But these lines are necessary to handle when to stop the program. The program is an active process until something stop it. If we don’t stop it, when our video has finished, it will be still executing. We don’t want. We would like to stop/close/finish our program when. Ok… but… what do we have to stop? We have to stop the loop. What loop?


Every pipeline contains a GstBUS by default. A GstBUS is a system which is watching out to some mesages; this messages could be for example: the EOS of the video or another messages. See We need to add a message handler to the bus of our pipeline using gst_bus_add_watch().


If you want to know more about the GstBUS, by the way. Look at this link:

We’ve already added the message handler, but now we need to add the function we’re going to use to handle the message. This function is busMessageCb. 'Cb’ from Callback. We connect the bus with this function with the following line.

    bus.connect("message", busMessageCb)

The function busMessageCb is created by the developer. The target of this function is to stop the loop create by Gtk.main() when the playing of the video has finished.

def busMessageCb(unused_bus, message):
    if message.type == Gst.MessageType.EOS:
        print "EOS: The End"

We’re finishing… this following line is just going to tell us what nanosecond of the video is the program playing each 300 miliseconds. Each 300 miliseconds our program will execute the duration_querier function which prints on the console the time of the video in a certain moment in nanoseconds.

    bus.connect("message", busMessageCb)

Finally, as an extra, I want this program being able to get closed when the user press “Ctrl+C”. The line below allow it. We’re taking advantage of the signal python library. And the program knows when “Ctrl+c” keys have been pressed because of the signal.SIGINT parameter. When these keys are pressed it calls to the function handle_sigint(sig, frame) which says “Bye!” and stop the loop.

    signal.signal(signal.SIGINT, handle_sigint)

April 08, 2014

How do you visually represent a project’s timeline?

Here is a fun example to illustrate why software development in general is a complex endeavour:

  1. You think you’re going to fix a tiny problem: “hey, maybe we could make ‘s welcome dialog look a bit nicer“.
  2. Eventually, someone proposes a design or idea that looks interesting, and you realize that to truly realize it, you should also implement an audacious new feature: a way to visually represent an entire timeline as a thumbnail (that one is an open question, by the way; if you have some clever ideas, feel free to share them)
  3. …and to display new feature B properly, you should also consider—ideally—being a good citizen and implementing feature C upstream, in the toolkit you use instead of doing your own thing in your corner.

This kind of serendipity and interdependence happens regularly in FLOSS applications like Pitivi where we prioritize quality over “meeting shareholders’ deadlines and objectives”, which is why we sometimes take more time to flesh out a solution to a problem: we aim for the best user experience possible, all while negotiating and working with the greater software ecosystem we live in, instead of silently piling up hacks in our application… and we depend on the involvement of everyone for things to progress.

March 21, 2014

GStreamer Hackfest and the first Beta release of Pitivi, “Ra is a happy”

Last week-end, part of the Pitivi Team went to the GStreamer Hackfest in Google’s offices in Munich to work with twenty other GStreamer hackers on various important technical issues. A big thanks to Google and Stefan Sauer for hosting the event! Keep your eyes peeled: we will soon blog the results of the work the Pitivi team has accomplished during the hackfest.

During the hackfest a very important milestone has been reached: the first GStreamer Editing Services, GNonLin and gst-python stable versions in the 1.X branch have been released. That means that these very central components of the Pitivi project are now considered stable.

While this backend work was essential to the beta release, we also want to specifically thank Alexandru Balut for his impressive involvement during the 0.92 -> 0.93 cycle. He provided an impressive amount of bug fixing and cleanup patches in Pitivi itself, and has greatly helped the project reach a beta state. Any inquiries regarding the 0.93 release codename must be sent in his general direction.

This release will be the basis on which we will start our work for our ongoing fundraiser. We’ve done that work in our spare time, and we’re excited about what we’ll be able to accomplish once we start working full time! Thibault Saunier has already been preparing bundles for the release, more on that in the next post!

Once again, you can help us in producing a rock solid stable release, by donating and spreading the message!

Pitivi 0.93 released

Last week, a flash snowstorm brought me around 2ft of snow overnight. I thought, “If I’m going to clear that much snow, might as well have some fun and make a timelapse out of it”, and so I did. While watching it, I realized, “Hmm… that’s an interesting metaphor for the huge amount of preparatory and cleanup work we’ve been doing in the past few years”:

Today, we’re very happy to announce another great Pitivi release. It brings a truckload of bug fixes and refinements, which you can read about in the 0.93 release notes (prepared by yours truly). This release now brings us to a quality level where we can let go of the “alpha” status and call this a “beta”. Many nasty bugs are gone and people are increasingly relying on it for their own projects. Besides the video above, the 2014 fundraiser‘s video and the Pitivi showcase, I was quite pleased to see someone using Pitivi to easily make a nice video for a commercial booth at a technology tradeshow!

0.93 is the result of continued efforts in our spare time—occasional hacking during vacations, nights and week-ends. Just imagine what could be achieved if Mathieu and Thibault could be funded to work full-time towards bringing us to 1.0!

Update: you may also want to take a look at this blog post.

March 04, 2014

Ayuda a PiTiVi a llegar a su versión 1.0

PiTiVi, el editor de video open source, ha iniciado una recaudación de fondos para poder llegar a su versión 1.0.

Como muchos de los usuarios de linux pueden saber, actualmente hay pocos programas de código abierto para editar video. A ello se le suma que ninguno de ellos son muy buenos. En los últimos dos años, PiTiVi ha pasado a usar una potente librería para edición de video llamada Gstreamer Editing Services (GES). PiTiVi ahora es una UI para esta librería. Los dos desarrolladores que trabajaron en GES han iniciado una campaña de recolección de fondos en Internet para hacer de PiTiVi una versión estable, ofrecer un programa de calidad y lanzar PiTiVi 1.0. Por ahora ya se ha recaudado más de un tercio del total (35.000 euros) en menos de dos semanas.

El lema de PiTiVi es “allowing everyone on the planet to express themselves through filmmaking, with tools that they can own and improve (permitir a todos en el planeta expresarse a sí mismos a través de la producción audiovisual con herramientas que ellos puedan poseer y mejorar)”. El equipo quiere construir una aplicación de edición de video flexible y de gama alta que pueda ser usado por profesionales o aficionados.

Desde un punto de vista técnico, PiTiVi es probablemente el editor de video opensource más prometedor (disponible en Linux) porque es respaldado por Gstreamer (un framework multimedia), el cual es usado por la mayoría de las distribuciones de Linux. Se ha requerido bastante tiempo por los desarrolladores de GES y Gstreamer. Usar una librería de edición de video de gama alta como GES hace relativamente fácil la tarea de crear un editor de video para adaptarlo necesidades específicas, por ejemplo. Todas las aplicaciones que usan Gstreamer (como Totem) se beneficiarán de su desarrollo.

Esta no es una inciativa personal. En primer lugar, dos es máß que uno. En segundo lugar, GES ha sido desarrollado con una colaboración muy cercana del equipo de Gstreamer. Además, hay otros desarrolladores y contribuidores involucrados, y cada verano aparecen los estudiantes que participan del Google Summer of Code. ¡La comunidad es muy activa!

El rol de esta camapaña es acelerar el desarrollo para conseguir nuestras metas más rápido. Las donaciones van a través de la fundación sin ánimos de lucro GNOME. Esto quiere decir que las donaciones en USA son deducibles de impuestos. Por favor, vea el video de la campaña y done en

Gracias :o)

March 03, 2014

Pitivi Fundraiser Week One Update (And A Great Piece Of News)

Greetings Pitivi supporters!

We hope everyone had a great week! We’ve had a rather hectic one, and hopefully that’s just the beginning. This is the first update for our fundraising campaign, be sure to check our blog weekly for more😉


We are happy to announce that the GStreamer maintainers decided to show us their faith and support, by allocating 2 500 € to our project from GStreamer funds! This is great news for several reasons:

  • It’s obviously nice to get such an amount of money as it represents seven percent of the total needed to get a 1.0 release or, to put it another way, three weeks of full time development!
  • GStreamer is the central component of our architecture, and it is the one on which we plan to spend most of our time during the push to 1.0. Pitivi really is just the tip of the iceberg, to put things in perspective, it now only is a mere 25,000 lines of Python code, whereas GStreamer and its plugins represent around 1.5 million lines of code.Our work really benefits every other project that uses GStreamer (for example, accurate seeking in ogg files? That was us!), and it is meaningful to see the GStreamer maintainers acknowledge that “officially”, many thanks to them! And then many more for the road. They’re awesome and a big reason why we love working on Pitivi.
  • We really hope this donation will help everyone that cares about Open Source, be they individuals craving for flawless multimedia handling on Linux or companies interested in building products around GStreamer, to see that we are an integral part of the community, and that donating to the campaign is not only about getting a great video editor, but also about improving the core multimedia engine shared by most if not all the Linux distributions!


We would like to thank each and everyone of the 350+ backers that already donated to the campaign and helped us break the 10 000 euros bar during this last week. 11 000 € is a great amount of money, sufficient to cover our expenses for three months of full-time development! With your help, we already made it to a third of our first goal, and with your help we can make it to Pitivi 1.0 and beyond. Anything helps, be it blogging, tweeting and sharing on social networks, or getting the word out to journalists.

DistroWatch also decided to make us the recipient of their monthly donation, and granted us 280 euros, it’s a great honor for us to be listed among the previous recipients of that donation!


The dictionary doesn’t seem to agree that this word should exist, but it’s here nevertheless. Next week should see an interesting announcement for all the fans of Python, Romania and clean code, make sure to stay tuned on our twitter or to add this blog to your RSS feeds😉

February 27, 2014

Pitivi status update for Q1 2014, fundraiser launch

Since my previous technical update in January, I haven’t had time to touch Pitivi’s code. Thankfully though, Alexandru Băluț has been filling the gap with a ton of refactoring work: around 150 commits! That took a fair amount of time to review and merge, believe me. Besides code cleanup, he also finished the port of the viewer to a cluttersink, fixed fonts and theme colors detection for the timeline (so it looks fine even if you’re not using the Adwaita GNOME theme).

Alexandru took the opportunity to not only fix some bugs, but also do some visual refinements on the timeline ruler: it now shows hours and miliseconds only when needed (depending on the zoom level) and subtly grays out units that did not change from one “tick” to another, so your eyes can focus on what actually changed:


More interestingly though, with the limited time available to me, I helped prepare Pitivi’s 2014 fundraising campaign. It involves a huge amount of groundwork from an administrative and marketing point of view. It’s been months in the making.

  • I’m glad that Mathieu and Thibault were able to spearhead the work of setting up the infrastructure, preparing the majority of written materials and setting up their legal and financial relationship with the GNOME Foundation.
  • Huge props to Fateh Slavitskaya and Bassam Kurdali for the great work they put into making the fundraiser video (I’m a filmmaker, believe me, I know how hard and time-consuming it is to get this done right, especially when you have voice-overs and 3D animation involved. Oh, and all the editing was done with Pitivi, VFX with Blender). Thanks to Thomas Vecchione for cleaning up the voice recordings and doing proper sound mixing for the video, I definitely can hear the difference.
  • Thanks to Oliver Propst for drafting initial contents for the FAQ and various emails that we had to send for outreach! It is always easier for me to start from existing contents rather than stare at a blank page (you could say I hate reinventing the wheel :)

And thanks to the 300 backers who believed in us and broke the 7000 euros bar in five days since the launch! This is a great start—it could pay for two months of full-time work for one developer such as Mathieu—but we need to reach the minimum of 35 000 and the target of 100 000 if we really want to achieve the goals we’ve set. Get involved and spread the word!

You may also be interested in the following blog posts that did not show up on Planet GNOME (but are visible on Planet Pitivi):

Oh, and besides our G+ page, we’re on Twitter now. I reclaimed control of our “brand” by kindly asking Twitter’s legal department (yes, really). Until now, the @pitivi account was held by someone unknown to us, inactive and unreachable since 2010, so it was not helping anybody:


It is now linked from the main website alongside other social gadgetry.

Also, some upcoming events:

February 26, 2014

Using GStreamer to make smooth slow motion!

This is a very good example of what our developers can do! There has been some preliminary work on bringing slow and fast motion to GStreamer and Pitivi, and a plugin has been created to allow for frame interpolation, which means you and I with our regular 24 frames per second cameras will be able to get smooth slowmotion from Pitivi in the future!

All that work has not yet been merged and thoroughly tested, and we need your help to make it happen!

To help you understand the difference between regular and smooth slowmotion, here is a video showing both types side by side, created by Alexandre Prokoudine. The difference is quite stunning!

Slowmo video effect with GStreamer from Alexandre Prokoudine on Vimeo.

February 25, 2014

Votes: a tool of engagement and development.

During the creation of the campaign, we debated what kind of perks we should offer. The thing is, we are not t-shirt creators, we are software developers and UI designers.

We believe people who give us money do so in order for us to develop a good software, and thus we tried to focus on perks that made real sense. What could we offer to the community that would help us in making the software that they truly want? Our answer to that question: a voice, simple as that.

Though we already have a very active community and listen to feedback from our users, we were missing a way to quantify the priority of feature requests for the people to whom our software matters enough to sponsor our work.

We decided on two types of perks we would offer: invitations to hangouts organized monthly (we’ll tell you more about that in a future post), and the subject of today’s post, our voting system!

We wanted to grant the possibility of voting to anyone who donated, from the lowest amount available, and decided to weigh the vote proportionally to the amount given, with steps at which the curve flattens a bit, to make sure people who can’t donate 300 euros still have a reasonable chance to have their voice heard.

Later I’ll post implementation details for those interested, on my personal blog. Suffice to say that it works, and more exciting that people are already making good use of it!

This brings me to the exciting news we want to share: we made the current vote results public! Obviously, as we’re in the early stages of the campaign, they’re not nearly as significant as they will be later, but we think it’s already interesting data, and you can have a look at them live right now .

Now to our own analysis of the data so far:

The first exciting figure for us is that even though we’re not yet guaranteed to reach a funding point that can put vote results into development (you can help us get there faster), one third of our backers already took the time to go through the form and rate features on the 0 to 10 scale, and we clearly expect that ratio to grow if we reach the 35,000 bar.

We interpret that as a sign that our voting system answers a real demand. This figure is a clear success in our effort to create sustainable community engagement to support responsive and dynamic Pitivi development, alongside the growing number of people who choose to put their faith in us and donate.

Some points in the feature ranking results caught our attention:

  • The clear first place of hardware accelerated decoding and encoding. This is really interesting to the engineers among us, who already salivate at the possible prospect of implementing it!It also goes to show that performance is critical to people using video editing software, and reassures us in our architectural choices: the decision to ally with GStreamer means a lot of the heavy lifting is done as part of a partner project that doesn’t have to be written by Pitivi developers from scratch. Instead, we contribute to GStreamer while also reaping the huge benefits of it — and that means we can focus better on the video editing side of our code (making sure dynamic pipelines work with hardware-accelerated decoders/encoders, adapting and extending our integration test suites to ensure it keeps on being true)
  • The very pragmatic second place of copy paste, a small but oh-so-helpful feature, which goes to show that our backers are sensible, productivity and detail-oriented people.
  • The low ranking of Windows and Mac ports, which is certainly due in part to the fact that awareness about our campaign is pretty much limited to the Free Software community for now.
  • Finally, something we don’t really know how to interpret on the spot, but that is interesting to remark nevertheless is that the three last spots are occupied at the time of writing by external project formatters, such as Final Cut projects.

I’ll repeat that these rankings are absolutely not definitive, as already existing backers can change their votes and new backers should hopefully continue to give their opinion on what matters to them.

The conclusion is: “Don’t like these rankings ? Donate and you can contribute in changing them!”

We’re really interested in your analysis of these early results, and hoping that discussion will occur about them in the comments section or on our IRC channel (#pitivi on freenode)!

Thanks for reading, the Pitivi team

February 21, 2014

Give some love to Pitivi !

Today we’re thrilled to announce a crowdfunding campaign to support the development of Pitivi!

We have made the choice not to use one of the major crowdfunding platforms such as kickstarter for multiple reasons, and instead partner with the GNOME foundation, which is ideologically aligned with us and will support our financial infrastructure.

We are proud of that partnership, as we share their objective of “creating a free software computing platform for the general public”, and the foundation is excited as well:

“GNOME is proud to host the Pitivi campaign. Pitivi fills a real need for stable and approachable high quality video editing. Its software architecture and UI design share the same sleek and forward-thinking approach that we value in the GNOME project.” — Karen Sandler, executive director of the GNOME Foundation

With that campaign, our aim is to provide everyone with a rock-solid Free Software video editor, based on the awesome technology that is GStreamer. We have spent a lot of time working on the campaign website, and it holds a lot more content than a simple blogpost could.

We know that what we want to do is the right thing, and requesting money for quality and stabilization first is the correct and honest thing to do. We obviously encourage you to donate to the campaign, but we also hope that you will be willing to spread the message, and explain why what we do is important and good.

Free and Open Source video editing is something that can help make the world a better place, as it gives people all around the world one more tool to express themselves creatively, fight oppression, create happiness and spread love.

Hoping you’ll spread the love too, thanks for reading !

February 15, 2014

Applying for a GSoC project is all about early involvement and commitment

This year, Pitivi‘s focus for GSoC projects will be a little bit different than in 2013. As you can see in our preliminary ideas page, there is much less GStreamer (or GES) work involved, as we tried to focus on Pitivi UI work — easier, concrete projects, mostly only in Python. Most of the hardcore backend work we needed to accomplish was done throughout 2013. Of course, there are still some hardcore project ideas around if you feel like you’re up for a challenge. Anyway, the list of ideas is just that: a list of ideas. We’re more than happy for you to come up with your own ideas (thinking outside the box is a positive trait, feel free to impress us).

More importantly, here’s how our approach differs this year:

  • We changed the application “procedure” (see the “How to apply and get started” section on the ideas page). Essentially, “discuss your ideas with us” has become step #3 instead of step #1. The first steps are now get your build working, test and use the application, figure out what you love and hate about it, and then start contributing some fixes immediately. This came out of the realization that this is what we actually tell everybody who shows up on IRC asking “I don’t know what to get started with as a contribution”: get the dev version, use it, then you’ll certainly see things you want to improve to get your feet wet.
  • Like one of the maintainers of Inkscape once said, I will not believe anything you write in your GSoC application. Your formal application is only 10% of the equation. We will base ourselves 90% on your involvement and demonstrated ability to contribute code to Pitivi. The more good-quality patches you’ve made, the more chances you have. As such, we expect you to start getting involved in February (March at the latest). If you only start hanging around by the time GSoC application period starts, you will need to work very hard to convince us that you have what it takes.

January 29, 2014

Presenting and hacking Pitivi at Pycon 2014

Pycon, or what I’d call the “main Pycon” (vs one of the sub-Pycons), has traditionally always been held in the United States of America. This year, it will be held in Montréal.


The most astute among you might have noticed that Montréal (Québec) is not actually in the USA (because trying to capture Québec City during a snowstorm on New Year’s Eve is a terrible idea).

Since Montréal is my homebase (and Pycon happening there might be the event of a lifetime), I decided to showcase… you guessed it: the new version of the Pitivi video editor.

  • I will be making a “scientific congress”-sized poster (122×122 cm, that’s 4×4 feet for you southerners). I enjoy distilling marketing contents into visually compelling print materials, so I’m pretty excited about making an unconventional, jaw-dropping poster. I’ll be using some Pitivi donation money to cover the printing costs (around 25$ according to UQÀM’s estimates, other places start at 90$…). If you have ideas of things I should have on the poster (besides nice charts/graphs, screenshots and artwork), feel free to comment.
  • I won’t be just talking in front of an unusually large piece of paper: it will be a live demo booth with Pitivi running in front of the poster (maybe I’ll need to get something better than a netbook…).

Besides talks, tutorials and poster sessions, Pycon also has sprints (which, as I understand it, are what I usually refer to as “hackfests”). So I will most certainly be looking to host a Pitivi sprint/hackfest from April 14th to 17th.

If you are attending Pycon this year, I hope you will drop by to say hi, try out the coolest pythonic open-source video editor out there or get started hacking on the code!

January 20, 2014

Announcing pitivi's fundraising campaign !

Our team

I've been a part of the Pitivi story on and off since three years now, whenever I could find time really. I've loved every moment I've spent in the community, I've made friends, I've learnt good engineering practices, how to fit in a team, how to communicate clearly, and so much more I can't even start to list.

Not gonna tell the whole story because that would be boring to write and even more to read, but eventually and naturally I became a maintainer alongside Thibault and Jean-François. Jean-François has been around the project for 10 years now, he's awesome, a really dedicated guy. Thibault and I are friends since a long time, well before I started programming, I've been his padawan for the best part of my initiation to programming and Free Software, and he's a great Jedi !

Recently, Alexandru Balut has also started to work with us again, I don't know him as closely as I know Jeff and Thib, but he's commited so much things in the last two months that we've had a hard time reviewing it and preparing the campaign at the same time ! I don't know him as well on a personal level as I know Jeff and Thibault, but I like working with him a lot, he makes great and clean patches and has a seemingly boundless dedication to cleaning up the code and making it elegant.

All this to say I'm proud and happy to be part of such a team. Free Software's most important asset isn't the code, the bug trackers, the continuous integration servers, it's the people, and these folks are great, I can't stress that enough.

Our project

You might have guessed by now that our project isn't to grow genetically modified potatoes in the Southern part of Italy, even though that seems like a compelling idea at first sight. Give it a second thought and you'll realize the hygrometry of that region is absolutely not appropriate, give it a third one for good measure then forget about it.

I'll briefly explain what it is that makes of the Pitivi project the most exciting open source video editing project in my very humble opinion. The reason goes down to our design choices. We've played the long game, and based ourselves on the gstreamer set of libraries and plugins. For a visual and greatly simplified explanation of how that choice is a good thing, you can refer to this animation, then have a look at the impressive list of plugins that we can tap into. GStreamer is where most of the companies interested in open source multimedia invest their money and their time, it's where most of the exciting stuff happens and it's definitely where an ambitious video editing application has to look at.

We also have made the choice of clearly splitting our editing core, our model, from our view, and made it a library, with an awesome API, gstreamer-editing-services, directly usable from C, C++, javascript, python and every language supported by introspection, and possibly any other language provided someone writes bindings for it. That choice was the right one, decoupling components always pays off in the long term, and we are finally starting to see the benefits of that choice: Pitivi has seen its size divided by two, while gaining in stability. This makes it much easier for new contributors to come in, and for us to maintain it.

tl; dr: GStreamer rocks, and GES is great. With that said, we are aware that the stabilization is not yet over. Pitivi is in a beta state, and it still needs intensive work to make it so we kill the bugs and they never come back. To do this, we must extend our test suites, we must continue collaborating with GStreamer devs, we must create better ways for users to share with us failing scenarios. For all this we've got great ideas, but what we miss is being able to work full-time on the project, which basically means we need money, for reasons I don't think I have to detail !

I'm afraid this might sound a little boring, as we all tend to be more attracted to feature promises and shiny things, and that's obviously what we all deserve, but I think that's not what we need right now (hope I got the quote right). Fortunately we estimate that phase to be around 6 months long for one person full time, we did *a lot* of the groundwork already, and we just have to expand on that, and track the corner cases cause the devil is in the details, and he knows how to hide damn well. After that, we will be ready to unleash GStreamer's power, and come up with great features in no time, and ride on the work of others to get for example hardware acceleration basically for free. From that moment, when we'll have released 1.0, things will get seriously real, and our backers will be able to vote on the features they care the most about. I've worked on the voting system and I think it's a great thing to have, I'm really impatient to see it used in real life (and hopefully not break), I think I'll write a more technical blogpost on its implementation.

How you can help.

I'm writing this the day before launching the campaign, and I have the website in the background, taunting me with its "0 € raised, 0 backers" message. Fortunately I also have the spinning social widgets to cheer me up a bit, but it's not exactly enough to get me rid of my anxiousness. I know that what we do is right, and that requesting money for stabilization first is the correct and honest thing to do. Obviously, I hope that you will donate to the campaign, but I also hope that after taking the time to read that rather lengthy blogpost in its entirety, you will be able to spread the message, and explain why what we do is important and good. Free and Open Source video editing is something that can help make the world a better place, as it gives people all around the world one more tool to express themselves, fight oppression, create happiness and spread love. Hoping you'll spread the love too, thanks for reading !

January 04, 2014

Scratching some Media Library itches

Besides catching a cold and shovelling snow, this holiday season I spent some time scratching itches in Pitivi. For starters, thumbnails generation: if you’ve been using the new Pitivi, you certainly ran into this:

medialibrary - partial thumbs

As you can see, thumbnails were not necessarily being shown for all clips. That was not the result of a buggy algorithm or anything like that (I don’t code often, but when I do, it’s perfect, of course), simply the fact that my solution for bug 432661 was partial: it would fetch the thumbnails if they already exist, but not create new ones.

Well, this is solved now. No more need to browse the folder with Nautilus to generate thumbnails! This does not block the user interface, thanks to Alexandru Băluț who helped me finish the job by correcting my incorrect attempt at threading with his own implementation.

medialibrary - complete thumbs

The only downside of the threaded version is that you lose the simple benchmarking system I had put in place, but no matter: I’ve measured the numbers already, so let me share them with you.

As you know, I’m pretty adamant about maintaining good performance and responsiveness in Pitivi, especially for operations such as importing clips or loading projects. I know that iconview can be slow, so my commit (before Alex’s changes) had various timers to check if searching through the iconview or updating its items was a significant performance problem. I tried with two scenarios: importing 68 clips to thumbnail, and importing 485 clips to thumbnail. Here are the resulting processing times in seconds:

68 thumbnails 485 thumbnails
Generation 20.131 141.059
Model search 00.1186 004.8595
Model insertion 00.0432 000.4

thumbnail pixbuf iconview model insertion benchmark

As you can see, for reasonable amounts of clips, the amount of time spent interacting with the iconview/treeview model, even using a naïve linear search, is insignificant:

  • The proportion of time spent searching increases when you have to generate hundreds of thumbnails, but it’s still mostly negligible (in the “worst case” shown here, it rises from 0.6% to approximately 3.4%).
  • Surprisingly, the time spent updating the model (inserting the pixbufs) is even more negligible than the time spent searching.
  • In the real world, it is unlikely that each and every thumbnail needs to be generated, searched and inserted. This happens only once in a while for a portion of your clips, not everytime you import each clip or load a project. No point in obsessing and complicating the code with caching, fancy search algorithms or data structures.

I’m hoping that we replace both the iconview and listview by a single “responsive” GTK FlowBox widget eventually, if FlowBox has better (or equal) performance than IconView, but this might take a while. If someone wants to tackle this or wants to help, please get in touch.

Better importing progress indication and error handling

First, the way we counted progression was wrong from a psychological standpoint. A bit tricky to explain, but the label needs to represent the position in the process (so eventually it reaches 100%), whereas the progressbar must hint at the amount of work remaining to complete (so it never goes to 100%).

Second, the error infobar’s “Close” button took an insane amount of space, which became quite apparent in verbose languages like French. GTK+ really didn’t want me to compact that button no matter what I tried, and using an icon instead of text didn’t yield as much space savings as using a single unicode character: ✖

Third, the error infobar was a bit of a tease: it told you that errors occured but did not tell you how many:

pitivi medialibrary error infobar - after

Well, now it does (you can also see the more balanced layout with the new ✖ button):

pitivi medialibrary error infobar - before

As you can see, when it comes to designing a good user interface, I’m kind of obsessive about details.


I also have a branch where Pitivi uses the client-side decorations and HeaderBar widget from GTK+ 3.10, however I’m blocked by the fact that GStreamer’s video overlay doesn’t work with client-side decorations:


In other news:

  • Alexandru Băluț fixed importing and timeline thumbnailing for MPEG-TS clips. He also spent a big amount of time and efforts on refactoring various modules.
  • Mathieu Duponchelle made rendering to MP4 and MPEG-TS possible again.
  • Jakub Steiner’s new super-high-res logo icon for Pitivi has been merged.
  • Tomas Karger got started on updating the user manual. It’s great to see someone new getting involved to finally give the user manual the attention it deserves! Thanks, Tomas.
  • I looked again into reimplementing the missing codecs installer dialog, but I’m blocked by the wrong information being provided by the discoverer error signals. On hold for now.
  • I implemented a very nice playback performance boost feature, but I’m blocked by the fact that it would pause the pipeline everytime a backup is saved in the background. Need to think of a solution for that without resorting to questionable hacks.

November 24, 2013

Wanted: documentation specialist

The Pitivi project is looking for someone who loves teaching/writing, to fill the position of “documentation specialist” among our team! The documentation specialist will be responsible for updating our fantastic user manual (online version here) based on release notes of 0.91 and 0.92 as well as your own imagination/ideas for improvement.

cat writing

The user manual is written in Mallard, but I can even accept contributions in plaintext (I would then do the markup myself). You only have to write it in English; other languages are handled by the hyperactive GNOME translation teams. You will receive:

  • No pay
  • No company-provided car, gym or insurance
  • Praise, hugs, possibly some beers at events such as GUADEC
  • Something great to put in your résumé/CV as a technical writer and contributor to open-source
  • The feeling of a job well done in a project that matters for the world
  • An autographed biography of Richard Stallman in French, if you’re into that sort of thing. I’m not even kidding, there’s a guy actually offering that as a perk on the Internet.
  • A gentle entry into the world of contributing to Pitivi if you want to go further

Apply now on #pitivi on !

November 04, 2013

Pitivi 0.92 and the wandering opensourcerer

The past few weeks have been pretty crazy.

At the last minute, I ended up going to the GStreamer Conference in Edinburgh, thanks to the GStreamer project sponsoring my attendance. As always, it was a fantastic event and it was great to meet up with old friends and see great topics being discussed. I was pretty impressed by the amount of attendees too. I’m feeling guilty for having missed good talks while being dragged into hallway discussions or being hammered by jetlag, but our pals at Ubicast recorded everything so I should be able to catch up later. My good friend Luis summarized the event much better than I could, so I won’t go into detail here. Except that Thibault won a bottle of whiskey and was unable to claim it, so I picked it up and brought it back for him (I don’t hack on GStreamer itself, so I don’t need the whiskey):


After gstcon, I embarked on a pretty hectic journey throughout Europe, with the goal of prospecting sustainable development opportunities and to eventually crash at Mathieu Duponchelle’s home in order to spend time on Pitivi together.

shadow of the colossus horse ride

Since I’m someone who tends to plan and optimize everything, hopping from city to city in a semi-improvised way over the past two weeks has been somewhat stressful. Especially the part where I found out the hard way that some capitals have their public transportation system to the airport shut down at night, or the part where I had to sleep on the floor in the entrance of the airport that was also closed at night even though you have flights departing before sunrise. That was fun. It is also a significant amount of transportation costs piling up (even though I’m an expert at minimizing them), so if you’d like to help offset some of the costs resulting from our current Pitivi activities, please feel free to tip a few bucks ;)

Managing and maintaining an established open-source project does not just mean coding: there is a lot of administrativia and planning involved, which has been consuming my free time lately. After discussions with Karen and Jim at the GNOME Montréal Summit, the post-GSoC stuff to deal with, the big research project I’ve been tackling and the research around the infrastructure needed for it, all on top of paperwork needing to be done at home during my absence, there was pretty much no time left for me to look at code. I somehow still managed to squeeze in a few commits to fix some blockers and a few trivial things, but that means that larger projects (even something as “simple” as reviewing a new set of icons) had to be renegotiated in my TODO list.


While staying with Mathieu in the past few days, we made some good progress on a big project coming up for Pitivi (more on that later) and released 0.92 to provide some fixes and polish over the earth-shattering 0.91. As you can see, this release comes just one month after the biggest release in years, so we are indeed aiming to get back onto a “release early, release often” cycle now. We hope you like it.

October 05, 2013

Pitivi 0.91 “Charming Defects”

And so it has come to this.


A few days ago, we stealthily published the tarball of the first Pitivi video editor release based on the GES engine. Incredible but true! 0.91 is finally out! In case you were living under a rock for the past two years, this release is the result of a major rework of the entire Pitivi architecture, and as such it is considered an “alpha” release. From a very (VERY) high level, it includes:

  • Replacing the core of Pitivi by GES; 20 thousand lines of code removed
  • Porting to GStreamer 1.x
  • Porting to GTK+ 3.x
  • Replacing GooCanvas by Clutter for the timeline
  • An automated UI test suite, with many checks for mission-critical parts
  • Fixing hundreds of bugs
  • Implementing many new features
  • UI polish all over the place
  • Refactoring pretty much the entire codebase

Since 0.15.2, over 1300 changes have been committed in Pitivi alone. That’s not even counting the incredible amount of work we’ve done in GES and GStreamer. See the details in the 0.91 release notes.

I would like to extend my deepest thanks to all the people who, through their contributions and the trust they have put in us over the past two years, have helped us achieve this milestone. The adventure continues however: we need your involvement more than ever to continue on the path we have set! If you’ve been shy about getting involved because of the huge amount of architectural changes we were going through, now is the perfect time to start contributing on fresh grounds.

Oh, and one more thing: “PiTiVi” is now known as “Pitivi”. Our website, documentation and infrastructure have been updated to reflect this small branding adjustment (the only part I didn’t update yet is the logo image). Moreover, in order to support open standards, free ourselves from YouTube (or any third party, really) and to make it easier to transition to a responsive design (more on that later), we now use HTML5 videos in open formats all across the website. Woohoo!

September 04, 2013

Fix it thrice

Some of you may be familiar with the good old “fix it twice” adage: fix the problem and then ensure it never happens again.

Last year, when I made Pitivi’s automatic backup feature work, I requested someone to write extensive automated tests for it (with Dogtail), so that I could feel confident about this feature never being broken again, even if it underwent massive refactoring or if everything else changed around it.

Turns out that it did break again this year. After the port to GES Assets and GES Project, loading a backup project would not actually populate the media library and timeline! The tests were not strict enough to check those kinds of “details”, so this flew completely under the radar.

I thought I’d fix the whole thing again… however, in addition to not wanting to see it break again later I wanted to be more efficient, so I did things differently this time: test-driven programming. I refactored our automated UI tests, made them much more exhaustive and sadistic, made them fail, and then spent time fixing the code until the tests would pass. And whenever I found another bug in that branch, I wrote tests to fail before I would fix the issue.

Now it works, and I can be confident about it again. I have effectively fixed it thrice.

Testing a bulletproof vest, 1923 - cropped

Why do I care so much about making it bulletproof? Because projects are Pitivi users’ most important data. It is critical to ensure their safety through unsaved changes warnings, disaster-proof automatic backups, backup restoring that actually works, and preventing accidental overwrites: Pitivi tries to gently steer you away from overwriting important stuff (you need to go through the “Save As” process and confirm the overwrite, if you consider the restored version to be the correct one). All that, and much more, is part of my automated tests.

Other recent stuff

Software Center description

I’ve been watching closely as Richard Hughes put forth a proposal for a new specification to describe applications in the GNOME Software Center. Here is what I wrote for Pitivi.


A video editor that aims to appeal to hobbyists and professionals alike, with a strong focus on usability, efficiency and quality


Integrating well with the GNOME desktop environment and other applications, Pitivi sports a beautiful user interface designed to be powerful yet easy to learn.

With a non-modal editing workflow, a framerate-independent and playhead-centric timeline, Pitivi allows you quickly and accurately trim, split and review your scenes. Pitivi’s ripple and roll editing features allow spending more time on storytelling and less time on “pushing clips around”.

Some other features include:

  • Accepts any file formats supported by the GStreamer multimedia framework
  • Can animate hundreds of special effects and filters with keyframable properties
  • Ability to set custom aspect ratios, framerates and rendering presets
  • Easy to use crossfades and SMPTE transitions
  • Multihead-friendly with detachable user interface components

Hopefully this should capture the essence of what it can do.

On a sidenote, we currently use INTLTOOL_XML_RULE to make this file translatable, and I heard that’s terribly uncool. Please help us by providing a patch to make it work using itstool instead!

New project render dialog, filesize estimates

It feels great when you pick up a patch you wrote “blindfolded” four months ago (back then, it was impossible to test) and see it “just work”: I had this small “Knuth” moment when it not only rebased cleanly, but worked as intended with only one or two Python syntax adjustments. The patch in question is a little feature I wanted to make it easier to figure out if the resolution/quality/bitrate settings I chose are getting me to get the kind of filesize I want: output filesize estimation.

2013-08-31 23:26:09

The algorithm I devised is naïve, but does the trick for the vast majority of cases. I cheat a little bit by waiting long enough to have gathered enough data for prediction to be somewhat significative, and by fuzzying the estimates — you’d be surprised how innacuracy can improve perceived accuracy!

While I was doing that, I started playing around to make the rendering dialog prettier and more informative. For starters, the “Rendering movie” header felt wrong for various reasons, and this became quite apparent once you add the “Estimated filesize” text right below it. Rewording the header to say something like “Your movie is now being rendered and encoded” didn’t help much.

That header was basically still duplicating what was in the window title. I pondered what could be put in its place; emptiness would look a bit silly, as the dialog would just be a titlebar, a progressbar and buttons. I then decided to put some informational text for educational purposes: few people actually understand what factors influence the encoding performance (or the speed at which your project renders), yet many people are surprised when it takes a long time, so I thought I’d add a contextual tip:

2013-09-01 00:14:09

2013-09-01 00:12:17

“What’s that ridiculous amount of empty space below the progressbar”, you say? A bug in GTK, it seems. I spent quite some time changing things all over the place until I discovered that making the window non-resizable “fixes” the issue. My guess is that GTK3’s size calculations are based on the height of the window before its width would be set by the “default width” property in my dialog… and then the height would never shrink. How odd. Anyway, the new text paragraph does prevent the window from being too narrow now, so the dialog doesn’t really need to be resized by users. Here’s how it looks like now:

2013-09-01 09:54:22

Certainly more useful than what we started out with, isn’t it? Paying attention to little details like that — having empathy for your userbase — allows creating what I call “intuitive” or “self-documenting” software.

Brace yourselves, 0.91 is coming

Oh, did I mention that Pitivi actually renders now? Well yes, that’s because we (especially Mathieu) have been doing a massive amount of work all across the GStreamer, GES and Pitivi stack to make this happen.

We have been incredibly busy in the past few months, pushing really hard to finally get a release out of the door by the end of the summer. In recent times, we have committed around 250 changes in Pitivi, 180 in GES, and I don’t know how many hundreds in GStreamer. My spare time was spent swimming through emails, having many technical discussions on IRC and dealing with hundreds of bug reports/issues/TODOs.

Working hard at GUADECWorking hard at GUADEC

With a few issues remaining (mainly related to scaling in videomixer), we’re now at the point where stuff… works. Audio mixing and video compositing are back (and keyframable), effect properties are keyframable, deadlocks and crashers are pretty much gone (as far as we can tell), etc. I’m starting to run out of bugs. Amazing!

We can finally make an alpha release in the near future.

How you can help with 0.91

0.91 will be our first alpha release based on GES. It’s a very exciting release with many improvements, bug fixes and new shiny things. You can help by:

  • Trying out the development version right now. Come have a chat and let us know how well it works for you!
  • Documenting. The user manual is quite outdated right now (it is still based on the 0.15 featureset). We need writers!
  • Helping me prepare the huge release notes. If you’re crazy enough.
  • Creating simple and lightweight test projects for Mathieu
  • Helping with packaging efforts (ensuring this can be packaged nicely, fixing build/setup issues etc.). Two issues you can tackle immediately are:
  • Revising the existing bug reports and doing a big triage cleanup
  • Hacking! As usual, we’ll be happy to help you get started.
  • Spreading the news

August 28, 2013

View Side-by-Side Stereoscopic Videos with GStreamer and Oculus Rift

Screenshot from 2013-08-28 16:36:17

GStreamer can do a lot. Most importantly it has the exact functionality I was looking for when I wanted to play a stereoscopic video on the Oculus Rift: Decoding a video stream and applying a GLSL fragment shader to it.

Available Players

I found a few solutions that to try to achieve that goal, but they were very unsatisfactory. Mostly they failed to decode the video stream or didn’t start for other reasons. They are not maintained that well, since they are recent one man projects with compiled only releases on forums. And worst of all, they only support Windows.

Surprisingly, I experienced the best results with OculusOverlay and VLC Player. Which transforms a hardcoded part of your desktop in a very hacky way with XNA. Works also with YouTube.

VideoPal is a player written in Java and using JOGL. In theory it could work in Linux but:

Exception in thread “main” java.lang.UnsatisfiedLinkError: Could not load SWT library. Reasons:
no swt-win32-3740 in java.library.path

Yeah.. no time for jar reverse engineering and no link to the source. I was able to run it on Windows, but it couldn’t open a H264 video.

There is also OculusPlayer using libvlc but does not release the source. The idea is good, but it didn’t work.

VR Player is a GPLv2 licenced Player written in C#. It also couldn’t decode the stream.

Another player is VR Cinema 3D, which does not play a stereo video, but simulates a virtual cinema with a 2D film. Funny idea.

Get some Stereo Videos

You can search for stereoscopic videos on YouTube with the 3D search filter. There a tons of stereoscopic videos, like this video of Piranhas.

Download the YouTube video with the YouTube downloader of you choice, which supports 3D videos. For example PwnYouTube.

For convenient usage in the terminal you should rename the file to something short and without spaces.

Using GStreamer

The minimal GStreamer pipeline for playing the video stream of a mp4 file (QuickTime / H.264 / AAC)  looks like this

$ gst-launch-1.0 filesrc location=piranhas.mp4 ! qtdemux ! avdec_h264 ! autovideosink

It contains the GStreamer elements for file source, QuickTime demuxer, H264 decoder and the automatic video sink.

If you want more information on the elements, try gst-inspect

$ gst-inspect-1.0 qtdemux

If you want audio you need to name the demuxer and add a audio queue with a decoder and an audio sink.

$ gst-launch-1.0 filesrc location=piranhas.mp4 ! qtdemux name=dmux ! avdec_h264 ! autovideosink dmux. ! queue ! faad ! autoaudiosink

Let’s add some Oculus Rift distortion now. We will use a GLSL fragment shader and the glshader element from the gst-plugins-gl package for that. Since the GStreamer GL Plugins are not released yet, you need to build them by yourself. You could use my Archlinux AUR package or the GStreamer SDK build system cerbero. Here is a tutorial how to build GStreamer with cerbero.

In the GLSL shader you can change some parameters like video resolution, eye distance, scale and kappa. This could also be done with uniforms and set by a GUI.

The final GStreamer pipeline looks like this. Since we are using a GL plugin, we need to use the glimagesink.


$ gst-launch-1.0 filesrc location=piranhas.mp4 ! qtdemux name=dmux ! avdec_h264 ! glshader location=distortion.frag ! glimagesink dmux. ! queue ! faad ! autoaudiosink

Seeking and full screen are features that could be achieved in a GStreamer python application.

June 08, 2013

Fun with videomixer


When you've spent the whole week painstakingly fixing bugs, coding something just for fun is a welcome breath of fresh air. These last weeks, one of my areas of work has been the gstreamer "videomixer" element. It needed some love, and still needs, but I've been able to fix some of the issues we had. When we first ported gstreamer-editing-services and gnonlin to gstreamer 1.0, even the most basic editing became impossible. That was quite frustrating to say the least, and being able to do edition once again feels extremely good !

One of the great things with the extraction of pitivi's edition code to GES is that you can now write fancy scripts to make automated edition, and with a little luck you won't encounter a bug on your way. At the end of this article, you will find a video showing an example result.

There haven't been much tutorials about using GES, the only way to learn that is either looking at the examples on the git repo, or to directly look at pitivi's source code. With that blogpost I'm gonna try to present that cool library, while coding something fun. The idea from the script came from that video :, linked to me by Nicolas Dufresne. We won't be able to reproduce the most advanced bits of this video, as it also seems to be content-aware at some points, but we will make a fun script nevertheless !

Sounds sweet, where's the code ?

Looks fine, explain it now !

I'll select the meaningful bits, assuming you know python well enough. If not, this is easily translatable to C, or any language that can take advantage of GObject introspection's dynamic bindings.

First, let’s look at the main.

    timeline = GES.Timeline.new_audio_video()

This convenience function will create a timeline with an audio and a video track for us.

    asset = GES.UriClipAsset.request_sync(sys.argv[1])
    audio_asset = GES.UriClipAsset.request_sync(sys.argv[3])

This is part of the new API. Thanks to that, GES will only discover the file once, discovering meaning learning what streams are contained in the media, how long it lasts and other infos. Previously, we would discover the file each time we created an object with it, which was not optimized. request_sync is not what you would use in a GUI application, instead you would want to request_async, then take action in a callback.

Now, let’s look at createLayers, which is where the magic happens.

    layer = timeline.append_layer()

A timeline is a stack of layers, with ascending “priorities”. Thanks to these layers, we are able for example to decide if a transition has to be created between two track objects, or, if two clips have an alpha of 1.0, which one will be the “topmost” one.

    clip = layer.add_asset(asset, i * Gst.SECOND * 0.3, 0, asset.get_duration(), GES.TrackType.UNKNOWN)

This code is very interesting. We are basically asking GES to : create a clip based on the asset we discovered earlier, set its start a i * 0.3 seconds, its inpoint (the place in the file from which it will be played) to 0, and its duration to the original duration of the file. The last argument means : for every kind of stream you find, add it if the timeline contains an appropriate track (here, audio and video). We could have decided to only keep the VIDEO, but that was a good occasion to show that.

With that logic, we can now see that the resulting timeline is gonna be sort of a “canon”: one video mixed with n earlier versions of itself.

    for source in clip.get_children():
        if source.props.track_type == GES.TrackType.VIDEO:
    source.set_child_property("alpha", alpha)
    alpha = mylog(alpha)

Here, I browse the children of my timeline element, and when I find a video element, I set the alpha of an element inside it, and update the alpha. The log here makes it so each layer has the same perceived opacity at the end.

Afterwards, we create a pipeline to play our timeline, and if needed we set it to the render mode, that code is quite self-explanatory.

We now just have to wait until the EOS, or until the user interrupts the program.

I use Gtk.main() out of pure laziness, a GLib mainloop would work as well.

How does it look like then ?

I really hope this example made you want to learn more about GES, it’s a great library that lets you do awesome stuff in very few lines of code, we’re in active development and the best is still to come !

Here is the promised video:

Notice the code was only tried with mp4 containing h264, feel free to report any issues with other codecs on my github !

September 03, 2012

KSE 0.1 released !

I just finished fixing the blocker bugs for the open source assets' manager KSE, and I pushed a release there : on the branch 0.1.

I recorded this screencast to make a demo of the features included in this release.

I want to say thank you to Simon Corsin for his work on the windows port and manual management.

I'd be glad to see pull-requests on github, or comments, critics and feature requests here.

Here is the text of the video for those with no audio:

Hi, my name is Mathieu Duponchelle and I am glad to present you the first release of kse, which is
a tool to simplify asset's management written in python.

This release covers spritesheet creation, sprite naming, automatic sprites detection in an existing spritesheet,
animation referencing and tons of other stuff.

Spritesheet creation.

Let's create a new spritesheet, and start importing resources.
First we create what we call an "atlas", specify its width and height and the location of the resulting file.
Then we can specify the size we wish the next sprite to have, and start adding sprites by double-clicking.
Next step is to start naming all these sprites, for now the naming part is a bit tedious, but it works.

Animation referencing.
Another cool feature of KSE is that we can reference animations easily, using multiple selection.
Let's say these sprites belong to the same animation.

We now save the project, and have a look at the xml that was produced.

We can see that a simple xml parser could easily extract coordinates for a given name, here X.

Automatic sprite detection.

Let's now say that we want to use an already existing spritesheet. I have this one, which will make for a good
A really cool feature is automatic sprite detection, which can be configured with this button.
Match-size will specify the desired width and height multiples for the resulting sprites.
Now let's try it out !
As you can see, KSE detected the sprites and automatically highlighted them. However, if the position or size
of any sprite does not match what we intend, we can easily resize and move them using the mouse or, if we want
a more fine-grained control the comboboxes that we have here.


With some friends of mine, we already developed a space shooter using KSE.
This helped me finding out the features that were most needed.
It can greatly improve the collaboration between designers and developers, by reducing the number of back and forth
trial and errors, allowing the programmer to only parse the xml file looking for the sprite or the animation name,
and thus not having to hardcode coordinates, which is an obvious advantage, and allowing the designer to try things
without having to modify the code or asking the programmer to do so.

KSE now works on both linux and Windows, it has not been tested on OSX yet.

My thoughts for future features are listed in the poll on the right-hand side of the blog, don't hesitate to comment if you have other ideas/remarks/critics. Thanks for watching !

July 17, 2012

Selectable layers

Finally, it’s done. Thanks to some hints in the source code of Jokosher I was able to implement selectable layers in PiTiVi.
The problem is that some widgets in Gtk+ don’t have gdk screens. This means that you can not change their background color, which is a really important thing for showing if a layer is selected or not.

The solution for this problem is to derive the widget from EventBox. This gives the possibility to modify the background using the modify_bg(…) function.

Based on that work I was able to implement proper selectable layers. So if you click on a layer control widget or a
layer in the canvas now, the layer gets selected and changes its background color. You can see a selected layer in the following screenshot. Note that I disabled all non-functional widgets (the entry, sliders, buttons…) for now, so this isn’t the final look.

Selected video layer

This work builds the base for more nice stuff like drag and drop layer reordering or menu actions on layers. I’ll cover these in the next post.

June 27, 2012

Week 1 & 2

Back from holidays I worked on including the newly created widgets in the user interface.

Before all video or audio layers only had one label. Now we want one widget for every audio/video layer. Therefore I had to change the internal logic quite a bit.

Afterwards I noticed that hard coded layer heights didn’t work well with the new widgets. The more layers you had the more you saw that they weren’t properly aligned. My solution for this problem is that I adjust the layer height to the height of the layer control widget. This also gives us basic folding support as well.

The current UI now looks like this:

PiTiVi screenshot with new layer control widgets.

You can find my branch on github. I’m also happy to hear your comments, hints or whatever you want to say🙂