Blog
Create a video transcoder GUI with Zenity and ffmpeg

Copyright © TechPad.co.uk
Create a GUI application for your Linux computer to allow you to graphically unleash the powers of ffmpeg to transcode video formats.
The Gnome desktop includes a very nice built-in application called Zenity, which allows you to create a simple dialog-based graphical user interface using a Bash shell script. Zenity is quite easy to use, when you get the hang of it, and making Zenity scripts is also a really good way to learn more about Bash and other Linux commands.
In this tutorial we're going to use four things, Bash scripting, Zenity, Awk and ffmpeg, to create a graphical user interface to the command line driven ffmpeg video transcoding application. When the script is finished, we'll add it to the Gnome Nautilus file manager so we can simply right-click on a video file and convert it into another format.
If you download videos from elsewhere and want to watch them on a portable media device, this could be just the thing you need. So besides being a useful guide to picking up some new skills, you'll also get a working application you can keep and use at the end. You can use the same principles to make graphical interfaces to any command line applications you want.
Right, let's get cracking!
Step 1: Install the software
If you're running Gnome, you won't need to install Zenity as it's part of the Gnome desktop. Likewise, Bash is installed already, as is Awk, but you may need to install ffmpeg - the transcoding application that we're using. On a Debian-based system, like Ubuntu, you can do this by entering the command:
sudo apt-get install ffmpeg
Step 2: Create a Zenity info dialog
Open up a text editor, such as Gedit, which is bundled with Gnome and add a line to the top of the file which reads #!/bin/bash. When you execute the script later on, this will start Bash and it will continue down the rest of the file executing the commands as it goes.
To keep the script a bit cleaner, we can create some constants to use throughout the script. We'll make one here for the window title, which we'll call WindowTitle. It's important not to leave any spaces between the variable name (WindowTitle) the = symbol or the content in double quotes, otherwise you get an error. We'll also create another constant called MessageIntro to contain a message informing the user of what they need to do.
Then, we'll kick off the script properly by using Zenity to create an info window. We'll set this to a width of 100 pixels and add an if/then statement afterwards, which will either continue or exit the script depending on what the user does.
#!/usr/bin/bash
WindowTitle="Video Transcoder"
MessageIntro="Please select the file you want to transcode"
$(zenity --info --title "$WindowTitle" --width 100 --text "$MessageIntro");
if [ $? = 1 ];
then exit
fi
Now, save the file as videotranscoder.sh. Go to your terminal, cd to the directory that the script is in and execute it by typing sh videotranscoder.sh
It should create an info window containing the text we defined above. If you get an error, check that you've got the spacing right. Bash is quite fussy about this.
Step 3: Create a Zenity file selection dialog
Now we need to get the user to select the file that they want to transcode and store the name and location of the file so we can use it in the command we give to ffmpeg. Since we're also adding some text to this file selection dialog, as we need to tell the user what to do, we'll also need to create another constant and add it to our list at the top.
MessageSelectFile="Please select the file you want to transcode"
To do this we need to use the Zenity --file-selection dialog option.This creates a GTK file selection dialog, just like the one you'll use every day on your Gnome desktop. Beneath the if/then statement on the first --info dialog we need to add the following code.
SourceFile$(zenity --title "$WindowTitle" --width 500 --text "$MessageSelectFile");
echo "Source: $SourceFile"
if [ $? = 1 ];
then exit
fi
Now, save your script and execute it by typing sh videotranscoder.sh and you should see a file selection dialog follow the initial info window. When you've selected your file, the details of it are stored in the SourceFile variable. We echo this to the shell so you can monitor what's happening when we run things from the command line, but you don't need to do this.
Step 4: Create a Zenity radiolist dialog
We want to allow the user to select what video format they want to transcode their source file to, and for this we can use the Zenity --radiolist option. This is quite similar to the radio buttons used in HTML, however, there's a little less control with Zenity.
We'll now create a Zenity command which creates a two column list of options. The user can then click the button next to the format they want and we'll store the value in a variable called OutputFormat.
We need to add two constants to our collection at the top of the script:
MessageSelectFormat="Select output format"
MessageSelectFormatVerbose="Please select the format you want to convert your file to"
Now we need to add another chunk of code beneath the last one we created to get the source file. Again, be careful with the spaces. If you miss them out, you could get errors when you run the script.
OutputFormat=$(zenity --title "$WindowTitle" | $MessageSelectFormat" --width 500 --list --text "$MessageSelectFormatVerbose" --radiolist --column "Select" --column "Output format" TRUE mp4 FALSE mkv FALSE wmv FALSE flv);
echo "Format: $OutputFormat"
if [ $? = 1 ];
then exit
fi
If you save the script and run it, it should now give you an info window, a file selection dialog and then a radiolist. The values stored should be echoed to the terminal.
Step 5: Create a Zenity entry dialog
We now want to get the user to provide a filename for the output file and we can do this with the Zenity --entry dialog option. In the constants section at the top of your script, you'll now need to add the following line:
MessageEnterFilename="Enter output filename"
MessageEnterFilenameVerbose="Enter output filename without suffix, ie. Shaun Of The Dead"
Then, beneath the last section we added, you need to add the code to create the Zenity --entry dialog.
OutputFilename=$(zenity --title "$WindowTitle | $MessageEnterFilename" --width 500 --entry --text "$MessageEnterFilenameVerbose");
Since spaces could be problematic, we'll also introduce an extra line in here which uses AWK to search for any spaces and turn them into underscores.This uses backticks ` not apostrophes, so make sure you use the right character. Add this below the last chunk of code.
OutputFilename=`echo "$OutputFilename.$OutputFormat" | awk '{$1=$1}1' OFS="_"`
This will convert a filename such as "Shaun Of The Dead.mp4" to "Shaun_Of_The_Dead.mp4", making it less problematic to store or pass to ffmpeg in our command line call, but it's not strictly necessary.
In closing this section, we'll as usual echo the variable we captured back to the terminal and add an if/then statement with an exit.
echo "Filename: $OutputFilename"
if [ $? = 1 ];
then exit
fi
Step 6: Create a Zenity directory selection dialog
We want to allow the user to choose where we store the transcoded file, and we can do this using the --file-selection dialog we used in step 3 with an added parameter called --directory. This simply allows you to select a directory rather than a file.
Add this line to your constants at the top of the script:
MessageSelectDirectory="Select destination directory"
Then, add this chunk of code at the bottom of the file. Again, we'll add an if/then statement and echo the response from the user back to the shell so we can check that it's all hunky dory.
Directory=$(zenity --title "$WindowTitle" | $MessageSelectDirectory" --width 500 --file-selection --directory);
echo "Directory: $Directory"
if [ $? = 1 ];
then exit
fi
Step 7: Execute the ffmpeg command and use Zenity progress
Now it's time for the exciting bit. We now have a little application which captures the following data from the user: the location and filename of the source file; the format the user wants to convert the file to; the location of the directory the file needs to be stored at, and the name of the new transcoded file. All we need to do now is pass all of this information to our command line transcoder ffmpeg.
We also want to give the user something to watch while the file is transcoding, so they know that the script has not just stopped, and for this we can use the --progress --pulsate command. This adds a progress bar to the application which pulsates from side to side. It doesn't show how long is left to run, but it does at least show them that something is happening, as transcoding can be a time-consuming process. Add this code to the bottom of your file.
ffmpeg -vcodec copy -acodec copy -i "$SourceFile" "$Directory/$OutputFilename" 2>&1 | zenity --width 500 --title "$WindowTitle | $MessageProgressTitle" --text "$MessageProgress" --progress --pulsate --auto-close
What this does is uses the same video codec (vcodec) and audio codec (acodec), takes the input file (i) from the $SourceFile variable and outputs it to the $Directory using the chosen $OutputFilename.
Then we pipe the output of ffmpeg using the "2>&1 |" part and add a pulsating progress bar and close automatically when we're done.
After you've added that chunk of code, you'll want to echo the command back to the shell and add the usual if/then bit.
echo "Command: ffmpeg -vcodec copy -acodec copy -i "$SourceFile" "$Directory/$OutputFilename""
if [ $? = 1 ];
then exit
fi
Now, you can run your script and test it out. It should work!
Step 8: Create an info window on success
When ffmpeg has done it's magic, we need to tell the user, so we'll trigger another Zenity --info window dialog to pop up at the end, then we'll exit the script. At the moment, the pulsating progress bar just disappears at the end.
We're going to add some text to our info dialog with the --text option and the variable $MessageComplete, so you'll need to add this to your collection of constants at the top of the script.
MessageComplete="Your file has been transcoded"
Then, you can close your script with the final info window, and echo a Done message in the terminal if the script is executed from the shell itself.
zenity --info --title "$WindowTitle" --text "$MessageComplete"
echo "Done"
exit
OK. We're done with the bulk of the scripting now. Give it a blast and see if it works. If you can't be arsed to type it all out, you can download a copy of the script here.
Step 9: Execute the script from your Gnome panel
To save you the bother of using the command line to start the script, you can add a shortcut icon for it to your Gnome panel. Right-click on the panel and select "Add to Panel" > "Custom Application Launcher" > "Add".
In the name field, enter a name for your script, ie. Video Transcoder. In the command field, enter "sh /home/matt/Scripts/videotranscoder.sh", where the path and filename matches yours. Click the icon on the top right corner to choose a custom icon to use, and then hit OK. You can now trigger the application from your panel without the need to open a shell.
Step 10: Add the script to your Nautilus scripts
If you want even more ease of use, you could now add the script to your Nautilus scripts collection. Nautilus scripts are shell and Python scripts that can be executed by right clicking on a file - so you'll be able to find a video that needs transcoding and select your transcoding application from the menu to have it converted in an instant.
Open the Nautilus file manager and click the small icon at the top right below the back button. The will open the location bar. In here, you need to enter /home/matt/.gnome2 (where matt is your username) and then hit return.
This will take you to the .gnome2 directory, within which you should find a folder called nautilus-scripts. Copy your videotranscoder.sh file into here.
Now open the directory and right click on your script then select "Properties" > "Permissions" > "Allow executing file as program".
Now find a video, right click it and select "Scripts" > "videotranscoder.sh" and your GUI should start up and allow you to convert the file.

If you can't even be bothered to read the above, you can jump straight to the code and save yourself the hassle of typing by clicking here.
Published: TechPad.co.uk Wednesday 30 December 2009, 9:49 am
Views: 899 times
Filed under: Zenity Bash coding Awk ffmpeg transcoding
Login to leave your comments
Please login










Recent comments
iplayer-dl is a Ruby application, which will run most easily on Linux or Mac (hence the Mac scree...
TechPad: 18:18 PM Aug 22nd, 2010
I don't understand how to use this. I have vista and firefox. Do I need to copy the iplayer int...
mufc1977: 15:15 PM Aug 21st, 2010
No worries, glad you got the buttons back in their rightful place!
TechPad: 13:13 PM Aug 12th, 2010
Disregard my previous comment: The FIRST time I tried it, it definitely didn't work. After addi...
freshrich: 1:01 AM Aug 10th, 2010
Great tutorial, but it doesn't work with Ubuntu Lucid. The only way I could get it to work was b...
freshrich: 1:01 AM Aug 10th, 2010