Monday, August 09, 2010

Bulk Video / Podcast Encoder for iPod / Mobile Devices

I have been using my BlackBerry and more recently my iPod nano to watch TV shows and several Revision3 podcasts which do not come in QuickTime format (Penn Jillette’s PennPoint). I have been using AKME FFmpeg for a few months to re-encode these videos, however, it is a pain to do only a few at a time manually. So I wrote this batch processor to work with AkmeFFmpeg.

Requirements: AkmeFFmpeg from http://sourceforge.net/projects/akmeffmpeg/
Suggested: SmartSync from http://www.smartsync.com/
Suggested: Juice from http://juicereceiver.sourceforge.net/

Language: C# .NET

What is AkmeFFmpeg?
AkmeFFmpeg is a simple yet powerful tool to re-encode audio-video such as
AVI, Flash FLV, MOV, MP3, MP4, WMV, 3GP. It puts a friendly GUI on the ffmpeg CLI to easily convert for YouTube or download to your BlackBerry, iPhone, iTouch, iPod, PSP, etc.

What is SmartSync?
It is a very simple GUI based application that can be used to sync directories on one or many computers.

What Does This Application Do?
It is an automated mass-converting tool that will allow you to re-encode your video files. Use this application with the task scheduler and your video files will be ready for your device by the time you wake up.

What this program does is it scans a directory and converts all of the videos in that directory to a new, smaller format and places them into another folder ready to be copied to your mobile device ("To Convert", and "Converted").

What I do is schedule this program to run every day at 3am and then I copy lots of video files into the "To Convert" folder. I also setup my podcast downloader (Juice) to download new postcast videos from Revision3 into this directory as well. Then the next day I just add the "Converted" folder to iTunes and download it all to my iPod Nano.

You will notice that the code below converts the videos to QuickTime mov files at a very low quality, that is because that is the only format my old iPod will play. However, you can change this to anything you like. Just download AKME FFmpeg and use the GUI to determine what the arguments for your specific needs should be.

 App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="SourceFileTypes" value="*.avi,*.mp4,*.mov" />
    <add key="RecursiveSourceDirectory" value="true" />
    <add key="SourceDirectory" value="C:\To Convert" />
    <add key="DestinationDirectory" value="C:\Converted" />
    <add key="ffmpegLocation" value="C:\Program Files (x86)\AKME\AkmeFFmpeg\ffmpeg.exe" />
  </appSettings>
</configuration>

Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Configuration;

using System.IO;

 

namespace VideoConverter

{

    class Program

    {

        //Get the variables from the app.config.

        public static string strSourceFileTypes = ConfigurationSettings.AppSettings["SourceFileTypes"].ToString().TrimStart(',').TrimEnd(',').Trim();

        public static bool bitRecursiveSourceDirectory = Convert.ToBoolean(ConfigurationSettings.AppSettings["RecursiveSourceDirectory"]);

        public static string strSourceDirectory = ConfigurationSettings.AppSettings["SourceDirectory"].ToString().TrimEnd('\\').Trim();

        public static string strDestinationDirectory = ConfigurationSettings.AppSettings["DestinationDirectory"].ToString().TrimEnd('\\').Trim();

        public static string strFfmpegLocation = ConfigurationSettings.AppSettings["ffmpegLocation"].ToString().Trim();

 

        static void Main(string[] args)

        {

            //Create the base directories if needed.

            if (!Directory.Exists(strSourceDirectory))

                Directory.CreateDirectory(strSourceDirectory);

 

            if (!Directory.Exists(strDestinationDirectory))

                Directory.CreateDirectory(strDestinationDirectory);

 

            //Process the root directory.

            processDirectory(strSourceDirectory);

        }

 

        private static void processDirectory(string strDirectory)

        {

            strDirectory = strDirectory.TrimEnd('\\');

 

            DirectoryInfo diRootDirectory = new DirectoryInfo(strDirectory);

 

            //If recursive is turned on and then process each sub-directory.

            if (bitRecursiveSourceDirectory)

            {

                foreach (DirectoryInfo diDirectory in diRootDirectory.GetDirectories())

                {

                    processDirectory(strDirectory + "\\" + diDirectory.Name);

                }

            }

 

            //Process each file matching the criteria.

            foreach (string strFileType in strSourceFileTypes.Split(','))

            {

                if (strFileType.Trim() != "")

                {

                    FileInfo[] fiFiles = diRootDirectory.GetFiles(strFileType);

                    foreach (FileInfo fiFile in fiFiles)

                    {

                        if (!File.Exists(strDestinationDirectory + "\\" + fiFile.Name + ".mov"))

                            processFile(fiFile.FullName, strDestinationDirectory + "\\" + fiFile.Name + ".mov");

                    }

                }

            }

        }

 

        private static void processFile(string strSourceFile, string strDestinationFile)

        {

            //Execute akmeffmpeg for each file using the following arguments.

            string strCommandArguments = "-i \"" + strSourceFile + "\" -f mov -s 240x134 -aspect 16:9 -b 128k -minrate 0k -maxrate 256k -bufsize 8192k -aq 128 -profile aac_low -y \"" + strDestinationFile + "\"";

 

            System.Diagnostics.Process proc = new System.Diagnostics.Process();

            proc.StartInfo.FileName = strFfmpegLocation;

            proc.StartInfo.Arguments = strCommandArguments;

            proc.Start();

 

            //Optional. Be warned that if you remove this, every file will be processed at the same time and your computer will become unusable, not an issue if you schedule this to run in the middle of the night.

            proc.WaitForExit();

        }

    }

} 

 

 

Copyright © Nathan Abourbih