How to combine video clips using ffmpeg and scripting

Combining video clips

Merging lots of short video clips into one longer video file can be a great idea. But if you’ve tried to manually merge videos in the past, you may know how difficult this can be. Not any longer!

Concatenating video clips with FFmpeg can be done loss-less, and it is super easy thanks to Fast video cataloger and some scripting.

This tutorial will show you have to write a script to, for example ,combine a list of video clips from your phone into a longer clip, or perhaps combining short clips you have downloaded from the internet.

Fast video cataloger gives you a good overview of all your videos regardless of how long they are.

Why not just use a video editor?

You normally edit videos using a video editing software, like the free Blender.

Tip: There is a little known video editor that comes with Windows 10. To launch it simply right-click a video and select open with “photo”. This editor allows lots of simple video editing operations like trimming a video or adding text.

But if your plan is to combine lots of small clips into a larger one, this is far more complicated than it needs to be. Worse, if you use normal video editing software, it is most likely going to recompress the video once you have finished editing. This not only takes time, but it will also reduce the quality of the video.

If the videos are the exact same dimension and have the exact same compression, you can probably concatenate them without recompression and quality loss.

And it’s not as complicated as it may sound.

Using FFMpeg

FFmpeg has this function build-in with its concat command, expplained in detail here.

With c# scripting in Fast video cataloger, we can create a simple script that takes your selected videos and concatenates them. If the selected files are similar we generate the needed FFmpeg command line and temporary files and launches the program. They are are not the same format we give an error message.

Extended video properties

This sample is hopefully doing something useful. But, it also shows how you can get and uses extended properties from videos in Fast video cataloger.

For this example to work we need the extended properties for video format, this is added by default in newer versions of Fast video cataloger if you have the right checkbox set in preferences (the default is on).

Extracting meta data from video

Setting for extracting meta data during the video indexing process.

Extended video properties

Extended video properties are displayed in the video properties window

We write the script so that if the properties are missing, we will just accept the video and let FFmpeg present the error message instead when there are issues.

The script

I have organized the whole script as a class so you can continue to build on it or bring it into other scripts easy. However, everything is really done in the Concat() member function to make it easy to follow.

Entry function

As always, all scripts start in the run function

static public void Run(IScripting scripting, string argument)

Here we just do a simple check that more than one video is selected. Then create the Concat class and call the Concat function on the newly created Merger object.

The concat class constructor simply takes the root script interface and saves it as a member.

The Concat() member function, as said before, is where we do everything.

FFmpeg

The first thing we do is getting the path to the FFmpeg command-line tool. If you have not already downloaded it you can do that from here: https://ffmpeg.org/ and make sure it is installed in c:\\ffmpeg\\bin\\ffmpeg.exe (or update the script to the path where it is installed).

Temporary file for listing the video files

Next, we need to create a temporary file. The temporary file will be the list of videos to concatenate that will be passed to FFmpeg.

string tmp_file_path = System.IO.Path.GetTempFileName();

Will generate a unique temporary filename in your “tmp” folder. (NOTE that if you have too many files in your tmp folder creating files there will fail. This is actually a pretty common cause for random Windows problems. I.e we need to make sure we delete the file when we are done)

var stream_writer = System.IO.File.CreateText(tmp_file_path);

Will create a text with the temp file name in your temp folder.

Checking if videos are compatible

Next, we will check if the format is similar for all videos selected. This is done by iterating over all videos and getting all extended properties for that video


var extended = catalog.GetVideoFileExtendedProperty((int)video_id);
foreach (var prop in extended )
{
// here is where we do the checking
}

and the check for video format looks like this. (In a real-world solution you would write a shared check function taking arguments on what to check but for this short example I think it would be harder to follow, so copy-paste it is )

if (prop.Property == "video_Format")
{
  if (video_format == null)
  {
    video_format = prop.Value;
    m_scripting.GetConsole().WriteLine( video_path + " - Video format is "  + video_format );
  }
  else if (video_format != prop.Value)
  {
    string msg = "Aborting. All videos must be in the same video format.\n'";
    msg += video_path + "' is in " + prop.Value + "\n";
    msg += " previous was in " + video_format + "\n";
    m_scripting.GetConsole().WriteLine( msg);
    can_do_pure_concat = false;
  }
}

 

The time we see the property we check we store it, the next time we compare it to what was stored. If they are not the same we print an error message and flag the that the list of videos is incompatible can_do_pure_concat = false. If you want to extend on this script you could use this flag and generate a different command line for re-encoding the videos.

Picking output video path

If we know the videos are compatible it is time to present a save dialog.


Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "concat" + extension;
dlg.DefaultExt = extension;
dlg.Filter = "All files|*.*";
Nullable result = dlg.ShowDialog();

Since we know the files are of the same format we suggest the file extension to be the same as the first video in the list.

Running FFMpeg

Now we have the list of source files, we know they are compatible and we know where we want the output file. It is time to call Fmpeg and merge the video.


System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "cmd.exe";
string cmd_line = " -f concat -safe 0 -i " + tmp_file_path + conversion_parameters + " -c copy \"" + out_file + "\"";
startInfo.Arguments = "/C " + tool_path + " " + cmd_line;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();

The /C switch to the windows command-line will close the window once the script has run to its end. If you instead use /K the window will remain on screen. That might be a good idea if you want to read error messages from FFMpeg.

Cleanup and playing the new video

Afte the command has run we should have a video. We need to clear up the temp file

File.Delete(tmp_file_path);

and finally, we use the windows shell to show the new video outside of Fast video cataloger.

System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo()
{
FileName = out_file,
UseShellExecute = true,
Verb = "open"
});

Running the script

To run the script load it into the script window in Fast video cataloger. Select the videos you want to concatenate and then click run. The program will check the file and present you with a save dialog to save the merged video and then play it with the default video player.

Here is the full script:

using System.Collections.Generic;
using VideoCataloger;
using System.IO;
using System;

public class ConcatVideos
{
static public void Run(IScripting scripting, string argument)
{
scripting.GetConsole().Clear();
ISelection selection = scripting.GetSelection();
List selected = selection.GetSelectedVideos();
if (selected.Count == 1)
{
scripting.GetConsole().WriteLine(“Select more than one video”);
return;
}

ConcatVideos merger = new ConcatVideos(scripting);
merger.Concat(null,null);
}

IScripting m_scripting = null;

ConcatVideos(IScripting scripting)
{
m_scripting = scripting;
}

public string GetFFMPEGPath()
{
string tool_path = “c:\\ffmpeg\\bin\\ffmpeg.exe”;
if (!File.Exists(tool_path))
{
System.Windows.MessageBox.Show(tool_path, “ffmpeg missing”);
}
return tool_path;
}

private void Concat( string out_file, string conversion_parameters )
{
string tool_path = GetFFMPEGPath();
string tmp_file_path = System.IO.Path.GetTempFileName();

var stream_writer = System.IO.File.CreateText(tmp_file_path);
if (stream_writer == null)
{
System.Windows.MessageBox.Show(tool_path, “Failed to write temporary text file”);
return;
}

ISelection selection = m_scripting.GetSelection();
IUtilities utilities = m_scripting.GetUtilities();
var catalog = m_scripting.GetVideoCatalogService();
string extension = null;
string video_format = null;
string video_width = null;
string video_height = null;
string audio_format = null;
List selected = selection.GetSelectedVideos();
bool can_do_pure_concat = true;
foreach (long video_id in selected)
{
var entry = catalog.GetVideoFileEntry(video_id);
string video_path = utilities.ConvertToLocalPath(entry.FilePath);

var extended = catalog.GetVideoFileExtendedProperty((int)video_id);
foreach (var prop in extended )
{
if (prop.Property == “video_Format”)
{
if (video_format == null)
{
video_format = prop.Value;
m_scripting.GetConsole().WriteLine( video_path + ” – format ” + video_format );
}
else if (video_format != prop.Value)
{
string msg = “Aborting. All videos must be in the same video format.\n'”;
msg += video_path + “‘ is in ” + prop.Value + “\n”;
msg += ” previous was in ” + video_format + “\n”;
m_scripting.GetConsole().WriteLine( msg);
can_do_pure_concat = false;
}
}
else if (prop.Property == “video_Width”)
{
if (video_width == null)
{
video_width = prop.Value;
m_scripting.GetConsole().WriteLine(video_path + ” – width ” + video_width);
}
else if (video_width != prop.Value)
{
string msg = “Aborting. All videos must be in the same dimension.\n'”;
msg += video_path + “‘ width is ” + prop.Value + “\n”;
msg += ” previous was in ” + video_width + “\n”;
m_scripting.GetConsole().WriteLine(msg);
can_do_pure_concat = false;
}
}
if (prop.Property == “video_Height”)
{
if (video_height == null)
{
video_height = prop.Value;
m_scripting.GetConsole().WriteLine(video_path + ” – height ” + video_height);
}
else if (video_height != prop.Value)
{
string msg = “Aborting. All videos must be in the same dimension.\n'”;
msg += video_path + “‘ height is ” + prop.Value + “\n”;
msg += ” previous was in ” + video_height + “\n”;
m_scripting.GetConsole().WriteLine(msg);
can_do_pure_concat = false;
}
}
if (prop.Property == “audio_Format”)
{
if (audio_format == null)
{
audio_format = prop.Value;
m_scripting.GetConsole().WriteLine(video_path + ” – Audio ” + audio_format);
}
else if (audio_format != prop.Value)
{
string msg = “Aborting. All videos must be in the same audio format.\n”;
msg += video_path + “is in ” + prop.Value + “\n”;
msg += ” previous was in ” + audio_format + “\n”;
m_scripting.GetConsole().WriteLine(msg);
can_do_pure_concat = false;
}
}
}
stream_writer.Write(“file ‘” + video_path + “‘” );
stream_writer.WriteLine();

if (!can_do_pure_concat)
return;
if (extension==null)
{
int extension_start = video_path.LastIndexOf(“.”);
extension = video_path.Substring(extension_start);
}
}
stream_writer.Close();

if (out_file == null)
{
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = “concat” + extension;
dlg.DefaultExt = extension;
dlg.Filter = “All files|*.*”;
Nullable result = dlg.ShowDialog();
if (result == false)
{
return;
}
out_file = dlg.FileName;
}

System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = “cmd.exe”;
string cmd_line = ” -f concat -safe 0 -i ” + tmp_file_path + conversion_parameters + ” -c copy \”” + out_file + “\””;
startInfo.Arguments = “/C ” + tool_path + ” ” + cmd_line; // use /K instead of /C to keep the cmd window up
process.StartInfo = startInfo;

m_scripting.GetConsole().WriteLine(“Running ” + startInfo.Arguments);

process.Start();
process.WaitForExit();

File.Delete(tmp_file_path);

System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo()
{
FileName = out_file,
UseShellExecute = true,
Verb = “open”
});

}
}

Writing scripts for Fast video cataloger

Writing scripts for Fast video cataloger

Fast video cataloger supports scripting in C#. You write script straight into he scripts window and run them by clicking run. If you want to be efficient it pays to spend a few minutes and setup a proper development environment.

Environment

Fast video cataloger has a text editor but it is really not great for writing code. It has no syntax highlighting and there is no help with the APIs. I highly recommend that you download visual studio from Microsoft, and download the real visual studio not the code version.

Downlloado visual studio

With Visual Studio, you will get a proper editor that knows C# and will provide syntax coloring. We have also created a Visual Studio project with all the samples. This solution let you compile all the samples to catch simple syntax errors right in the environment. The solution produces an output file but that one is of no practical use so ignore that artifact. The only use of the visual studio solution is as a help for writing scripts.

Another benefit of using the provided solution is that you will get full IntelliSense to help with the scripting API as well as with any other .net library you might want to use. Add your own script to the solution and develop them there.

The documentation

When you install Fast video cataloger there are two documentations installed. The normal program documentation and scripting documentation in the form of a “scripting.chm” in the install folder. The scripting documentation details the whole scripting API and what you can do. Scripting in Fast video cataloger is focused on the actual catalog and not the user interface. You can make a lot of changes directly to the catalog but for the user interface to reflect the changes you need to explicitly call the Refresh() function from the script to force the user interface to reload from the state of the catalog.

There are also higher-level user interface functions in the program that are not exposed to scripting. For example, the repair functions can not be scripted. It is possible to write your own repair function using the API but we have not exposed the high-level user interface. Scripting by clicking menus and buttons in the interface should be possible using ui automation tools but that is the type of native scripting we talk about here.

The samples

When you install fast video cataloger a number of sample scripts are also installed in the Scripts/Samples folders. They are documented in the scripting documentation and the visual studio solution loads them all so it is easy to look at the code.

Writing your own scripts

When starting writing your own scripts I highly recommend starting with one of the supplied scripts. Find the script that is most close to what you want to do. Make a copy of that script. Add it to the sample solution and change the class name to something suitable. Build the solution to ensure it compiles and continue from there.

How to run scripts

Scripts are run from the script window as mentioned before. When you run a script you can also provide a string as an argument. Use this as a way to customize your script without having to edit the actual script. You load a script by clicking the “Load” button. If you are working with the script in visual studio you can reload the same script from the same file by holding Shift when clicking the Load button. That way you don’t need to pick the same file every time you need to reload the script as you are developing it in visual studio. (Selecting run in Visual studio will not work as we are not compiling a program and there is no way for Fast video cataloger to know you have clicked F5 and that one of your scripts is loaded in the program)

Setting up an action button for a script

Once you have a script you are happy about and expect to use often as part of your workflow it is time to bind an action to it. Actions are created from the preference dialog.

Action to run a script.

An Action will create a button in the Action window, in the “Custom Action” area and you can run your script just by clicking that button.

If clicking the button does not work there is probably something wrong with your script. Remember that the script is run and error messages are printed in the console window.

Setting a shortcut to a script

If you have a script you really use a lot it is possible to first create an Action and then bind a shortcut to that Action from the Shortcut window.

References

Most of the samples provided use the same resources as the standard .net library, these references are included by default and you only need to add a “using” line at the top of your script. If you want to use references that are not available by default you will need to add a comment starting with “//css_ref” followed by the reference you want. So for example //css_ref PresentationCore; references the Presentation core.



//css_ref WindowsBase;
//css_ref PresentationCore;
//css_ref PresentationFramework;
//css_ref System.Runtime
//css_ref System.ObjectModel

This is similar to a C# application where you would add a reference in the visual studio solution. To work with the sample solution you would need to include the reference in the solution to get it to compile and the //cs_ref line to get it running inside Fast video cataloger.

WPF and XAML resources

Since Fast video cataloger is running scripts and compiling the c# file when the script is loaded it won’t work with compiled XAML files. It is still possible to use WPF but you will need to load the XAML file dynamically.

If you have not done so already, download Fast video cataloger and try to write some scripts.

Guide to recent How To articles about Fast video cataloger

Recent article overview about how to use Fast video cataloger

The last months we have added lots of information on how to use Fast video cataloger. Here is a quick guide to help you quickly find what might be useful for you.

New articles about how to use the software

Learn how you can use Fast video cataloger as a video library when you are live streaming in “video library for live streams”

Learn how to find identical or similar videos to save some space and clutter in “easy-way-to-find-similar-videos”

Learn how you can use the integrated companion image features in Fast video cataloger in “Managing photos and video images for your video files/”.

Fast video cataloger has an integrated file organizer. Learn how to organize your actual video files using this functionality in “How to work efficient with video folders/”.

This text, “How to work faster with videos in Fast video cataloger/”, is a favorite of mine. It goes through a bunch of small features that can save lots of time if you are a frequent user of Fast video cataloger.

“Video wall” is one of the unique features in Fast video cataloger. In “video-wall in Fast video cataloger/” we explain the feature in more detail. If you have not tested it already you owe it to yourself.

Learn how to get highest quality videoplayback in Fast video cataloger by reading “Using madvr for high quality video playback/”.

New articles about how to use the scripting functionalities

Scripting is not for everyone, there is a learning curve. But, if you are interested in automating tasks or extending the software we have added a bunch of new articles for you. And we have more text planned for the coming month. Maybe you know someone that is a programmer who would like to try it out?

In “Exporting thumbnail files from videos using c#” we show how you export the video thumbnails to jpeg files on disk. This will be useful when you want to use the images in another software or perhaps a web page.

In “Import videos from all my movies by Boildesoft” we show how you write a script that reads data from a standard Access database.

In “c# for all the really advanced video searches” we show how you may extend the search function to fit your specific need. This can be combining search criteria from external data or just be outside of what you can do with the user interface in Fast video cataloger.

New version (6.18) available for download

New version available

Today we released Fast video cataloger 6.18 and you can download it from here. You might have noticed that there has been a bunch of releases since the major 6.1 we released back in August. We have basically released one update every week. The reason is that we decided to have a period of focus on quick bug fixing and hold off from major new features. We already have lots of features in the program. We do need to do a better job of explaining the features to users. Since our current focus is on fixing isues there is much less testing needed before releasing a new version. We can, therefore, have quicker turnarounds.

If there are things you would like to see fixed or that you think we should explain better please contact us.

On the area of explaining better we have posted a bunch of recent blog posts about how you can use the program. If you have not seen them already do have a look.

Recent improvements

Some of the improvements we have done the last month or so are:

  • Improvements to the scripting API as well as updated documentation and more samples. And, we have added a bunch of new articles about scripting on the web page. If there is something you are missing in the API to do what you want to do, do not hesitate to contact us.
  • Lots of Bug fixes. Whenever the program crash you get the option to upload a crash dump to us. We have been looking close at the issues reported and fixed a bunch of problems. If you get the dialog please take the time to upload it and write a sentence about what you did when the crash happened.
  • Improved indexing. We fixed issues with some older video formats and we have fixed issues with timeouts during indexing.
  • Fixed various issues with the integrated “file organizer”. The preferred way to move files in Fast video cataloger is to drag from the “video catalog” to the target folder in the file organizer.
  • Fixed issues with archiving when it could just fail in some cases
  • Fixed issues with multiselection.

We will keep working on minor improvements for a while so do check back from time to time to get the latest version of the software.

Video library for live streams

Video clips for live streams

Regardless if you are a veteran streamer or just starting out, a key to a successful live stream is forming a bond with your audience. You need to react, communicate and interact with them and never ever be boring. Having quick access to a video library for live streams lets you be more responsive, and, it will make your stream more interesting and less boring.

Fast video cataloger let you build a video catalog and then quickly search, browse and find the video clip you are looking for. With Fast video cataloger, you will have quick access to all your clips live while you are streaming.

Live Streaming setup

If you are streaming videos on youtube you probably know about OBS Studio?

OBS Studios is free and open software that let you set up a streaming studio. You can combine a number of video sources to a live stream or record it to a file. The sources can be for example one of your computers screen, a web camera, images or video clips.

A typical setup is to have one screen where you do your screen recording and one screen, that is not broadcast, where you have the OBS studio software window.

You will also run Fast video cataloger on that second screen. Or, an even better setup, the third screen with just Fast video cataloger. You can use it quickly to find a video for your live stream from your entire video library. Once you have found the video you want to broadcast you simply drag the videos from the video catalog window to the OBS window and it is live.

video library for live streams using obs studio and fast video cataloger

(Tip: If you can not drag the video from the video catalog window make sure the file organizer is present in the fast video cataloger layout. Click “view” and click “file organizer” ).

You do not need to do this all live. You can prepare before your broadcast. Drag over clips you think you will need for your broadcast. But, even if you prepare, being able to also change that programming is going to give you an edge over your competition.

Finding the video in Fast video cataloger is super quick and you will instantly have access to your entire video catalog. Having access to all your videos allows you to be more spontaneous and interactive with your audience.

Of course, you do not need to use the OBS studio software. The same technique to set up a video library for live streams will work with other streaming software as well.

You can download a free fully-functional trial version of Fast video cataloger from here.

Exporting thumbnail files from videos using c#

Saving thumbnails

Sometimes you need a video thumbnail for use outside of Fast video cataloger. You can easily just right click the thumbnail and select “save as”. This is fast and easy if its a single thumbnail you want to save but it will be very time consuming if you want to save all thubmnails for a video, or for several videos.

This is a good example of where the scripting support in Fast video cataloger can help, and it is really easy.

Exporting thumbnails from C# script

This example shows how to export out all thumbnails for the currently selected videos as files.

For each video we create a foder called thumbnails in the same folder as the video file. Then we get all the thumbnails for the selected video by calling GetThumbnailsForVideo(video_id, true );
we get all the thumbnails and only need to go through them all, generate a filename and call System.IO.File.WriteAllBytes(filename, image_data);
to write out the image to file.

using System;
using System.IO;
using System.Collections.Generic;
using VideoCataloger;
using VideoCataloger.RemoteCatalogService;

class ExportThumbnails
{
    static public void Run(IScripting scripting, string arguments)
    {
        scripting.GetConsole().Clear();

        var service = scripting.GetVideoCatalogService();
        ISelection selection = scripting.GetSelection();
        List selected = selection.GetSelectedVideos();
        foreach (long video_id in selected)
        {
            var video_file_entry = service.GetVideoFileEntry(video_id);
            string target_folder = video_file_entry.FilePath; 
            int path_end = target_folder.LastIndexOf('\\');
            target_folder = target_folder.Substring(0, path_end+1);
            target_folder += "Thumbnails\\";
            try
            {
                DirectoryInfo info = Directory.CreateDirectory(target_folder);
            }
            catch (Exception ex)
            {
                scripting.GetConsole().WriteLine( ex.Message );
            }

            long image_no = 1;
            Dictionary thumbnails = service.GetThumbnailsForVideo(video_id, true );
            foreach (KeyValuePair thumbnail_entry in thumbnails )
            {
                byte[] image_data = thumbnail_entry.Value.Image;

                string filename = target_folder + image_no.ToString() + ".jpg";
                scripting.GetConsole().WriteLine("Saving image to : " + filename);
                System.IO.File.WriteAllBytes(filename, image_data);
                image_no++;
            }
        }
    }
}

Easy way to find similar videos

This text will tell you how to find similar videos but first let us take a look at how you can find completely identical videos.

Finding identical videos

Fast video cataloger is a great way to organize your video clip collection, download it from here.

If you have a large collection it easily happens that you have the same video in different locations, perhaps in different file formats or in different resolutions. Having all these versions of a video can take a lot of space. The first step in cleaning up your location is finding the duplicate videos so you can pick what to keep and what to remove.

Fast video cataloger has a great way to find duplicate videos in your collection. From the Repair dialog you can use the “Check duplicate videos” tab to search the entire collection for duplicate videos. At the end, you will get a list of videos and can select which one to keep. The check for duplicate video function uses checksums to ensure the files are identically the same. I have written a step by step text about how to use this tool earlier

However, if a video has a different format or different resoluton this tool will not detect them as duplicate.

An easy way to find similar but not identical videos

Here is a simple manual process you can use to find videos that are similar but not exactly the same.

Start with an empty catalog and set it to index videos with just a few images per video. You can use your normal settings but, we only need a few thumbnails per video, so changing the settings can save you some time.

Then index the videos.

Once done go to the video catalog in detail view (the default one) and click on the “Length” column to sort all videos based on the length of the file.

Click the length column to sort on length to help you find similar videos.


Next just scan through the thumbnail images in the video catalog list to find pairs of thumbnails that look the same. Since you sorted on the length of the video they will be close together, as most videos will not have the exact same length.

If the thumbnails look the same click on the videos and make sure all of the thumbnails look the same, pick the video you want to keep and continue.

Even if the videos have different codecs or are of different resolutions this manual process makes it really quick and easy to find similar videos after you have cleared out the exact duplicates.

Import videos from All My Movies by BoildeSoft

All my movies

All My Movies by Boildesoft ( https://www.bolidesoft.com/allmymovies.html ) is a software that lets you manage your collection of bought movies. It downloads movie data from the imdb database and many other services (http://imdb.com). It also let you track and rate movies you have watched.

If you compare to Fast video cataloger the focus of All my movies is toward collecting movies while Fast video cataloger is geared toward organizing any type of video clips you have on your computer or in your organisation.

Importing videos from All my movies

This sample script shows how to use the scripting support in Fast video cataloger to import data from an All my movies database. The full script is included at the end, simply load the script into the script window in Fast video cataloger and run it.

Database format

All my movies uses an Access database with the extension set as .amm. If you rename the file extension to .mdb you can load it straight into Access and have a closer look at the data. To be able to read the Access database in a program you need to install the Access database engine. Download it from here. Since Fast video cataloger is a 64 bit program make sure you install the 64 bit version of the database engine.

Import videos script

The script to import videos is pretty straight forward. To make it easy to follow I have put it all in the entry function. If you want to expand on this script you should split it up into a number of functions and you should add error handling.

First we show a dialog to let the user pick the All my movies database file to read from:


Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.FileName = "access"; // Default file name
dlg.DefaultExt = ".mdb"; // Default file extension
dlg.Filter = "mdb file (.mdb)|*.mdb|AllMyMovies file (.amm)|*.amm|All files (.*)|*.*"; // Filter files by extension
Nullable result = dlg.ShowDialog();

We then open the database file and runs a simple SQL query to get everything from the movies table in the database.


OleDbConnection connection = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + dlg.FileName + @";User Id=admin;Password =;");
connection.Open();
OleDbDataReader reader = null;
OleDbCommand command = new OleDbCommand("SELECT * from movies", connection);
reader = command.ExecuteReader();

Next we create some new extended properties for the catalog. Some of the properties in All my movies are not in the list of default video properties. But, since you can add your own properties in Fast video cataloger we will also do that for these properties.


var catalog = scripting.GetVideoCatalogService();
catalog.SetPropertyMeta("video_property", "year", "edit");
catalog.SetPropertyMeta("video_property", "studio", "edit");
catalog.SetPropertyMeta("video_property", "trailer", "edit");
catalog.SetPropertyMeta("video_property", "length", "edit");
catalog.SetPropertyMeta("video_property", "comments", "edit");

Then we read each line of the movie table in the database to create video entries.

while (reader.Read())
{
  string name = reader["Name"].ToString();
  string path = reader["LocalPath"].ToString();
  string description = reader["description"].ToString();
  string url = reader["url"].ToString();
  int video_id = catalog.AddVideo(path, name, 0, description, 0, 0, url, null, 0, null, null);

Once we have the video created we get the id of the newly created video and can use that to set the extended properties.

  string year = reader["year"].ToString();
  catalog.SetVideoFileExtendedProperty(video_id, "year", year);
  string studio = reader["studio"].ToString();
  catalog.SetVideoFileExtendedProperty(video_id, "studio", studio);
  string trailer = reader["trailer"].ToString();
  catalog.SetVideoFileExtendedProperty(video_id, "trailer", trailer);
  string length = reader["length"].ToString();
  catalog.SetVideoFileExtendedProperty(video_id, "length", length);
  string comments = reader["comments"].ToString();
  catalog.SetVideoFileExtendedProperty(video_id, "comments", comments);
}

Finally, we close the Access database and refresh Fast video cataloger to show the imported videos.


connection.Close();
scripting.GetGUI().Refresh("");

Conclusion

It is pretty easy to import data from All my movies into Fast video cataloger. You can use the same techniques to import data from other software, or, your custom solutions into Fast video cataloger. If you have imported a file to the video you can select “reindex” on the videos. Then the program will scan the video file for thumbnails and extended properties.

Below is the full script. You can also find the file in the sample script folder when you downlod Fast video cataloger.

using System.Collections.Generic;
using VideoCataloger;
using Microsoft.Win32;
using System;
using System.IO;

namespace VideoCataloger
{
    using RemoteCatalogService;
    using System.Data.OleDb;

    public class ImportMDB
    {
        static public void Run(IScripting scripting, string argument)
        {
            scripting.GetConsole().Clear();

            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.FileName = "access"; 
            dlg.DefaultExt = ".mdb"; 
            dlg.Filter = "mdb file (.mdb)|*.mdb|AllMyMovies file (.amm)|*.amm|All files (.*)|*.*"; 
            Nullable result = dlg.ShowDialog();
            if (result == true)
            {

                try
                {
                    // https://www.microsoft.com/en-us/download/details.aspx?id=13255
                    // to download the access database runtime of the provider is not installed
                    // note you need the 64 bit version

                    OleDbConnection connection = 
                    new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" 
                    + dlg.FileName + @";User Id=admin;Password =;");
                    connection.Open();
                    OleDbDataReader reader = null;
                    OleDbCommand command = new OleDbCommand("SELECT * from  movies", connection);
                    reader = command.ExecuteReader();

                    // Setup the extended video properties
                    var catalog = scripting.GetVideoCatalogService();
                    catalog.SetPropertyMeta("video_property", "year", "edit");
                    catalog.SetPropertyMeta("video_property", "studio", "edit");
                    catalog.SetPropertyMeta("video_property", "trailer", "edit");
                    catalog.SetPropertyMeta("video_property", "length", "edit");
                    catalog.SetPropertyMeta("video_property", "comments", "edit");

                    while (reader.Read())
                    {
                        string name = reader["Name"].ToString();
                        string path = reader["LocalPath"].ToString();
                        string description = reader["description"].ToString();
                        string url = reader["url"].ToString();

                        int video_id = 
                        catalog.AddVideo(path, name, 0, description, 0, 0, url, null, 0, null, null);

                        string year = reader["year"].ToString();
                        catalog.SetVideoFileExtendedProperty(video_id, "year", year);
                        string studio = reader["studio"].ToString();
                        catalog.SetVideoFileExtendedProperty(video_id, "studio", studio);
                        string trailer = reader["trailer"].ToString();
                        catalog.SetVideoFileExtendedProperty(video_id, "trailer", trailer);
                        string length = reader["length"].ToString();
                        catalog.SetVideoFileExtendedProperty(video_id, "length", length);
                        string comments = reader["comments"].ToString();
                        catalog.SetVideoFileExtendedProperty(video_id, "comments", comments);
                    }

                    connection.Close();
                    scripting.GetGUI().Refresh("");
                }
                catch (Exception ex)
                {
                    scripting.GetConsole().WriteLine( ex.Message );
                }
            }
        }
    }

}

c# for all the really advanced video searches

Extending the video search

The basic idea I show you here is how to write a script in C# that determines if a video matches your search criteria or not and put the matching videos in a custom Bin.

You will learn by a simple step by step example how to write a script that goes through all videos in you catalog and puts all short videos(the critera we have as an example) in a bin.

After you have this skill you can expand your skill and continue to experiment.

About the native video search

Fast video cataloger has a very powerful, fast and simple search engine. The text below show how easy you can extend it even more with advanced custom video search in C#.

Our simple user interface make searching in Fast video cataloger straight forward for everyone. However, we do not provide a SQL interface for search so there are searches you can simply not express given our user interface. With the scripting interface you can do basically anything.

AI For example… What if you want to search with facial recognition or object detection or the next big thing in AI and video?

You an do all this and more by leveraging the scripting capabilities in Fast video cataloger

step by step breakdown on the Video search script in c#

Run(…) in the code below, is the entry function where the execution of the script starts.

    static public void Run(IScripting scripting, string argument)
    {
        FilterToBin instance = new FilterToBin(scripting);
        instance.SetBinTarget("short videos");
        instance.Filter();
        scripting.GetGUI().Refresh("");
    }

I have encapsulated all functionality in a class called “FilterToBin” that has two functions.

SetBinTarget() let you set the name of the Bin that will be used for search results. Please note that this Bin will be cleared every time you run the search.

Filter() does the actual filtering of videos.

    private void Filter()
    {
        var catalog = m_Scripting.GetVideoCatalogService();

        VideoQuery query = new VideoQuery();
        VideoFileEntry[] videos = catalog.SearchVideos(query);

        long bin_id = CreateBin();

        foreach (VideoFileEntry entry in videos)
        {
            if (IsVideoPassingFilter(entry))
                catalog.AddVideoToBin(entry.ID, bin_id);
        }
    }

The Filter() function first does a search to get all videos. In this example we pass in en empty VideoQuery object. That will give us all videos in the catalog. You can of course leverage the search here and first do a high level search to get a subset of your videos and then apply a more advanced search on that subset.

We then call CreateBin() to ensure we have a bin to put our results in. If we look closer in the FilterToBin class the CreateBin member function has some logic to create a Bin if its not already created and clear it from videos if it already exists.

Finally we iterate over all videos and call the IsVideoPassingFilter() function on each video. Videos that pass the test are put in the result Bin.

    private bool IsVideoPassingFilter( VideoFileEntry entry )
    {
        if ( entry.LengthSeconds < 60)
            return true;
        return false;
    }

If you want to change the filter criteria this is the only function you need to edit. In this example we only check if the video length property is smaller than 60s.

To run this script you copy paste it or type it (or load it) into the script window and then click the Run button.

Go the Bin window and select the "short videos" to see the result (if the bin is not there go into the edit bin to refresh the window, this is needed on older versions of Fast video cataloger).

Edit button in bin window

Edit button in bin window

Full source code in C#

using VideoCataloger;
using VideoCataloger.RemoteCatalogService;

public class FilterToBin
{
    IScripting m_Scripting;
    string m_BinLabel;

    FilterToBin(IScripting scripting)
    {
        m_Scripting = scripting;
    }

    private void SetBinTarget(string bin_label)
    {
        m_BinLabel = bin_label;
    }

    private void Filter()
    {
        var catalog = m_Scripting.GetVideoCatalogService();

        VideoQuery query = new VideoQuery();
        VideoFileEntry[] videos = catalog.SearchVideos(query);

        long bin_id = CreateBin();

        foreach (VideoFileEntry entry in videos)
        {
            if (IsVideoPassingFilter(entry))
                catalog.AddVideoToBin(entry.ID, bin_id);
        }
    }

    private bool IsVideoPassingFilter( VideoFileEntry entry )
    {
        if ( entry.LengthSeconds < 60)
            return true;
        return false;
    }

    private long CreateBin()
    {
        var catalog = m_Scripting.GetVideoCatalogService();
        Bin[] all_bins = catalog.GetAllBins();
        foreach (Bin bin in all_bins)
        {
            if (bin.Label == m_BinLabel)
            {
                VideoFileEntry[] videos = catalog.GetVideosInBin(bin.BinID);
                foreach (VideoFileEntry entry in videos)
                {
                    catalog.RemoveVideoFromBin( bin.BinID, entry.ID );
                }

                return bin.BinID;
            }
        }

        Bin target_bin = catalog.CreateBin(m_BinLabel, -1, 0xffffff);
        return target_bin.BinID;
    }

    static public void Run(IScripting scripting, string argument)
    {
        FilterToBin instance = new FilterToBin(scripting);
        instance.SetBinTarget("short videos");
        instance.Filter();
        scripting.GetGUI().Refresh("");
    }
}

Managing photos and video images for your video files

Images and video files

Fast video cataloger lets you manage any type of photos together with your video files.

In Fast video cataloger, everything starts with a video. Fast video catalog is far from a traditional photo viewer program.

For photos, this means that you link photos to videos and that photos are filtered for the video.

We call photos stored in Fast video cataloger for companion images.

Companion images can be any type of digital image in jpeg or png file format.

What companion images you want in your catalog depend on the application. If you have a catalog of normal play films, like a movie you would find at imdb. Then, typical companion images are probably cover images, posters, pictures from the release party.

If you use Fast video cataloger for your company. Then, the companion images could be images shot at meetings and presentations, photos of a whiteboard, people in the meeting and so on. For these applications remember that you can also add extended video properties. In that way, it is possible to link other file types to your videos.

Type of images that fast video cataloger can handle

A companion image is any type of image set to a video. A companion image can be set as cover a front or back cover for a video. We also have the concept of Actor portrait image and Actor companion image.

How to add photos to your catalog

The easiest way to add images to a catalog is to add them automatically when you add a video to your catalog. You can control if and how companion images are added from the preferences. The program can automatically add companion images that are stored in the same folder or subfolder relative to the video file.

The companion image browser has a button to rescan a folder structure. Use this if to add companion images to a video that was scanned without images.

You can also go into the repair function and do a scan to find companion images in a subfolder to videos that are not in the catalog.

Add companion images by dragging the image files to the companion image window.

Video companion images

Browsing photos for a videos

The “companion image browser” window displays thumbnails of the companion images for the selected video. The “preview image” window shows the selected image (and you can zoom with the mouse wheel).

The “Cover” window only shows the front and back cover image for the video.

The “Companion & Cover image” is a more compact window that combines the above three windows into one. It shows a scrollable list of thumbnails. When you move the cursor to the bottom of the window it lists all companion images. The currently selected image is displayed in the same window.

In the “Attract cover images” window you can see a slideshow of random cover images for all videos in your collection. There is also a setting in the preferences, “Include Companion images”. When this is checked you will get all companion images for all videos, not just covers.

Attract window

Nice things with companion images

If you have companion images setup for a video you can move it in the file organizer and the companion images will move with the video files.
Right-click in the “companion …” window you can select to use a cover image as the image to represent a video in the video catalog (for example a cover).