The start/help window in Fast video cataloger is a web browser. It uses the chromium embedded framework and you can access and use it easily from scripts.
You get the browser interface from the standard scripting interface
var browser = scripting.GetBrowser();
To open a web site in the browser you would simply write: browser.Address = "https://google.com/";
And here is a full example:
using System.Runtime;
using System.Collections.Generic;
using VideoCataloger;
using VideoCataloger.RemoteCatalogService;
class Script
{
static public async System.Threading.Tasks.Task Run ( IScripting scripting, string arguments )
{
var browser = scripting.GetBrowser();
browser.Address = "https://google.com/";
}
}
The use of the browser has almost endless possibilities. You can use it to present information and info from your scripts, you can fetch data from other systems or even create custom user interfaces.
Have you ever wanted to create keywords based on the filename of a video?
With the scripting support in Fast video cataloger, this is actually pretty easy. Here is a sample script to do just that, create keywords from the filename or path of a video.
The provided script takes the currently selected videos and adds keywords and actors based on the name of the video file.
You might want to tweak the script a bit to suit your own naming standard.
The array of separators list the characters that should be treated as keyword separators.
The array ignore_words is a list of common words that should simply be ignored and not added as keywords.
The integer min_length is the number of characters that a word needs to contains to be added as a keyword.
Finally, if a string contains the @ character that sentence will be treated as an actor. First name before the @ and last name after the @. The actors are created and added as cast to the video.
As usual, to run a script in Fast video cataloger you load it into the console window and click the Run button.
Script console and web browser open.
#region title_to_keywords
using System;
using System.IO;
using System.Runtime;
using System.Linq;
using System.Collections.Generic;
using VideoCataloger;
/// <summary>
/// Take the title and use it to generate keywords.
/// If there is a @ in the title we treat that as an actor
/// the text before @ is first name and the text after is last name
/// if an actor with that name already exist we use that one.
/// </summary>
class KeywordsFromTitle
{
static public void Run(IScripting scripting, string arguments)
{
scripting.GetConsole().Clear();
var catalog = scripting.GetVideoCatalogService();
ISelection selection = scripting.GetSelection();
List<long> selected = selection.GetSelectedVideos();
foreach (long video in selected)
{
// Get the video file entry
var entry = catalog.GetVideoFileEntry(video);
scripting.GetConsole().WriteLine(System.Convert.ToString("Processing..." + entry.FilePath));
char[] separators = { ' ', ',', '.', '-', '[' ,']', '{', '}', '_' };
string[] ignore_words = { "is", "are", "who", "where" };
string title = entry.Title;
string[] keywords = title.Split(separators);
int min_length = 3;
foreach (string word in keywords)
{
if (word.Length>= min_length)
{
if (!ignore_words.Contains(word))
{
if (word.Contains("@"))
{
// Actor
string[] names = word.Split('@');
string first_name = names[0];
string last_name = names[1];
scripting.GetConsole().WriteLine( "Actor FirstName:"+ first_name + " LastName:" + last_name );
int actor_id = -1;
VideoCataloger.RemoteCatalogService.Actor[] current_actors = catalog.GetActors(null, first_name, last_name, true);
if (current_actors.Length >= 1)
{
actor_id = current_actors[0].ID;
}
else
{
VideoCataloger.RemoteCatalogService.Actor actor = new VideoCataloger.RemoteCatalogService.Actor();
actor.FirstName = first_name;
actor.LastName = last_name;
actor_id = catalog.AddActorToDB(actor);
}
if (actor_id != -1)
catalog.AddActorToVideo(video, actor_id);
}
else
{
// Keywords
scripting.GetConsole().WriteLine("Keyword:" + word );
scripting.GetVideoCatalogService().TagVideo(video, word);
}
}
}
}
}
// refresh the gui to show the changed file paths.
scripting.GetGUI().Refresh("");
}
}
#endregion
Here is a short sample script to search for a video file in the catalog given a filename.
Simply use the search api and provide the VideoQueryProperties. FilePath is a part of the video path you are searching for.
If the search failes to find any videos it will return null.
If it finds videos it will return an array of VideoFileEntry. The entries includes, among other things, the ID of the video. You use the id as key for the other APIs.
As usual, copy paste the script into the script window in Fast video cataloger. This is just a small sample, if you are developing your own script make sure to check our other developer resources.
using System.Runtime;
using System.Collections.Generic;
using VideoCataloger;
using VideoCataloger.RemoteCatalogService;
class Script
{
static public async System.Threading.Tasks.Task Run ( IScripting scripting, string arguments )
{
scripting.GetConsole().Clear();
VideoQuery query = new VideoQuery();
query.Properties = new VideoQueryProperties();
query.Properties.Description = "";
query.Properties.Link="";
query.Properties.Title = "";
query.Properties.FilePath = "part_of_filename";
VideoFileEntry[] result = scripting.GetVideoCatalogService().SearchVideos( query );
if (result!=null)
{
foreach (VideoFileEntry entry in result)
{
scripting.GetConsole().WriteLine( "ID=" + entry.ID );
}
}
}
}
I will show you how to access the web browser in Fast video cataloger to easily integrate a web search with your video catalog. In Fast video cataloger 6.31 we opened up the integrated web browser in Fast video cataloger for scripting. If you are on an older version please update to the latest version from our download page or click the upgrade button in the program.
Web browser window
The web browser is what you see when you click on the view button and Help.
Click the help button to open the web browser.
Here is how it looks with just the script console and the web browser open in Fast video cataloger.
Script console and web browser open.
Scripting the browser
IScripting has a new member function GetBrowser(); that will get you the top-level interface to the integrated chromium web browser. The complete interface is documented on the cef GitHub site. To load a web page to the browser window you simply need to call Load() and give your URL as argument.
To get the underlying browser object and access the dom model you can call GetBrowser() to get and IBrowser object. The IBrowser interface has a MainFrame property of type IFrame and from here you can get access to execute javascript. That is outside the scope of this text, let me know if you are interested in more example on how to use that functionality.
Google search
You can do google searches by giving the right arguments to the google URL. http://www.google.com/search is the root URL. Search arguments are passed as q=[search terms]. Search terms need to be separated by a + sign. There are plenty of extra arguments to customize your search, for example, as_filetype=[file extension] to search for a specific filetype or as_sitesearch=[site URL] to search only at a specific site. In this example, I will only use the basic search query but you can easily expand on it to fit your needs. Remember to use & between arguments if you want to send more than the q argument y.
The search sample
We start by getting your current video selection. Then we fetch the VideoFileEntry for that selection using the VideoCatalogService interface. This is very similar to most other samples. Then we do a bit of string manipulation. Spaces in the Google query should be separated by + so we replace all spaces and also all _ as they are probably meant as spaces in the title. Last we check if the title has a “.” in there somewhere and get rid of everything after the . as that is probably a file extension. Now we have the string we want to search for. We need to pass this to google as q= so we put that in the query string.
Next, we get the browser with GetBrowser() and then call Load() with the Google base URL and the search query.
Script Code
Copy-paste the following into the script console to use the selected video title as a search term on google. Click Run to execute the script.
using System.Runtime;
using System.Collections.Generic;
using VideoCataloger;
using VideoCataloger.RemoteCatalogService;
class Script
{
static public async System.Threading.Tasks.Task Run ( IScripting scripting, string arguments ) {
var selection = scripting.GetSelection();
List selected_videos = selection.GetSelectedVideos();
if (selected_videos.Count>0) {
var cataloger = scripting.GetVideoCatalogService();
var video_entry = cataloger.GetVideoFileEntry( selected_videos[0] );
string title = video_entry.Title;
title = title.Replace(' ', '+');
title = title.Replace('_', '+');
int extension = title.LastIndexOf(".");
if (extension!=-1)
title = title.Substring(0,extension);
string query = "q=" + title;
var browser = scripting.GetBrowser();
browser.Load("http://www.google.com/search?" + query);
}
}
}
TMDB (The Movie DataBase ) is a large open internet database you can use to search for movies, tv shows, and people in movies. It also has a web API.
Fast video cataloger is a software to organize video clips so you can quickly search, browse, and find what you are looking for.
This example will show how to use the scripting support in Fast video cataloger to integrate with the web API in TMDB. My goal is to show you have to integrate a search for actors using the TMDB web API and then add the metadata to Fast video cataloger. With this start, I hope you can expend it to what you need and perhaps use other functions in the TMDB API.
Script demo
Getting started
If you do not already have Fast video cataloger installed you can download a free trial from here
Before we can start you also need to create a free account at TMDB that you can get from here, When you have your account to go your profile, click settings and find the API tab and request a developer API key.
The script we show here can be downloaded from our sample git hub repository
Place the downloaded scripts get_actor.xaml and get_actor.xaml.cs in the script folder of your fast video cataloger installation.
Open the get_actor.xaml.cs and fine the line near the top that reads
static string api_key = "";
and replace the empty api_key string with your TMDB API key.
Running the script
To run the script in Fast video cataloger open the Script console window. In the window click on the Load button and load the get_actor.xaml.cs script. Click run and you should see a window like this:
Integrating with tmdb people search
Search for an actor and you should see something like this
results of a search in the movie database
You can then click “Add to catalog” to add the actor to your Fast video cataloger database
Script overview
The C# script that is running uses WPF for the user interface. The user interface is defined in the XAML file. We use the rest API for TMDB. You can find full documentation for it here
Note that this sample just uses a minimal subset of the TMDB API. But, the principles are the same for the whole API, and it should be pretty easy to extend this with more functionality. For example, getting poster images or searching for movies.
Another difference to most other Fast video cataloger samples is that this one uses async programming which is needed for the web APIs.
Script walkthrough
You can find the full xaml file here and the full source file here
References
At the very top of the script we need to add our external references. This is what normally would go into “references” in a visual studio c# project. In a Fast video cataloger script you use a comment in the format of :”//css_ref [dependency]”.
//css_ref WindowsBase;
//css_ref PresentationCore;
//css_ref PresentationFramework;
//css_ref System.Runtime;
//css_ref System.ObjectModel;
WindowsBase, PresentationCore, and PresentationFramework are needed for the WPF user interface. System.Runtime and System.ObjectModel has the c# code we need to access and parse the web API.
Static variables
At the top of the script, we have a few static variables. The important one here is again the api_key variable, here you need to fill in your key as mentioned earlier.
Entry point
Run is the entry point of all scripts running from Fast Video cataloger:
static public async Task Run(IScripting scripting, string argument)
The only thing we do in the entry function is to save the passed in scripting interface and then create the GetActors WPF window and show it. We intentionally call Show() and not ShowDialog() since we want to be able to bring up the actor window in Fast video cataloger when we have this window open.
Constructor
In this example, we have put all code in the HelloWindow class. This has the same structure as the basic HelloWpf.cs sample.
The constructor loads the XAML interface definition and sets up the window. It also establishes the connection between the buttons and their click functions (unfortunately we do not support binding directly in the XAML as the XAML file is loaded through the script engine ).
Searching
When the search button is clicked we will get a callback to Search_Click(…). This is the main function that performs the search. We first fetch the text the user entered in the search box.
Then we call SearchActors asynchronously and expect to get a CPersonSearchResult back, more on that later.
After that, we have to check if we got a search hit. In this example, we only care about the first result but you can of course list all the results and let the user pick one of them.
We have our first actor and pick the name. We then call MakeProfileImageUrl(…) to generate a URL for the profile image. We call GetImageData(…) to get the image from that URL.
At this point, we have most of the data we need.
We create a new Actor class in the Fast video cataloger format and store that in m_CurrentActor. We fill in the data members with data from the search and the downloaded portrait data.
Next, we call GetPerson() with the TMDB id for the first actor. Once we have done that we have all the data we need from TMDB.
We create a WPF image from the downloaded image data and call SetActorToUI() to update the user interface.
SetActorToUI()
This function simply updates the user interface from the variable we have designed. The portrait is set to the image, the name and the description is set. The XAML file defines the whole layout of the user interface including size and positions of elements and fonts.
Adding to Fast Video cataloger catalog
If you click add to catalog after you have searched and found an actor you will get a callback to AddToCatalog_Click(…). Here we simply get the interface to the video catalog and call AddActorToDB() with the m_CurrentActor we filled in earlier when we got the search result.
GetConfiguration()
GetConfiguration() is a wrapper to load the TMDB configuration. You only need to call this once in your application and it is needed to among other things figure out the path to any image resource. The configuration is stored globally in m_Configuration. This is a very short function and it is a good example of how to use the TMDB rest API.
First, we create the URL that we will use to access TMDB. It always starts with the base URL and then the API we want to use and some arguments. Among the arguments, you always pass in your API key. We then use this URL and call one a utility function, GetFromJSON(), we have in the sample code. This function takes a class argument, which is of type of the JSON file we want to get from the URL. And, it returns an object of that class or null if it fails.
Let us take a closer look at that utility function.
GetFromJSON()
GetFromJSON() is an asynchronous function that you pass the class of what you want to read from the query string. There is some initial setup and then we call GetAsync( query ) that will asynchronously call the URL and get the result. Once we have the result we read the data from the response message as a string. We then create a memory stream to the string data and create a DataContractJsonSerializer object to parse our data from the JSON data and create the C# object.
public async Task GetFromJSON(string query)
{
T parsed_stuct = default(T);
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var client = new HttpClient(handler);
try
{
var videoGetIndexRequestResult = await client.GetAsync(query);
var result = videoGetIndexRequestResult.Content.ReadAsStringAsync().Result;
var ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(result));
var serializer = new DataContractJsonSerializer(typeof(T));
parsed_stuct = (T)serializer.ReadObject(ms);
ms.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return parsed_stuct;
}
If you want to use other parts of the TMDB API you need to create classes for the data that are returned by the functions.
SearchActors( string query )
The SearchActors() function is very similar to the GetConfiguration() function but it uses the search/person API. We pass the api_key but also some extra arguments.
One of the arguments is a query string, this needs to be URL encoded to handle special characters like spaces.
Then again, once we have our URL, we simply use the GetFromJSON() utility to read the result into the CPersonSearchResult class. This class includes info about how many results you have from your query and some basic information about each result returned in an array of class CActorResult. Here you have the name of the actor, an id that we can use in other API calls and a profile_path. Profile_path is needed when you want to create an URL to fetch the profile picture.
MakeProfileImageUrl()
MakeProfileImageUrl() is a utility function that is used to generate an URL to a profile image. For this, we need the configuration data where you have the base_url for all profile images. We need to decide on the size of the image, the different types of sizes are also listed in the profile image, and then finally we need the part of the URL that is unique for every actor. Once we have this URL we can just get the data.
GetImageData()
GetImageData() takes the URL from MakeProfileImageUrl() or really any image URL in the TMDB image URL format. We again use the WebClient API and call DownloadDataTaskAsync(). This function will asynchronously download the image data to an array. This is the right format we need to pass to Fast video cataloger. But we need one more step to display it in the WPF user interface.
private async Task GetImageData(string url)
{
byte[] image_data = null;
try
{
Uri image_url = new Uri(url);
var webClient = new System.Net.WebClient();
image_data = await webClient.DownloadDataTaskAsync(image_url);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return image_data;
}
LoadImageFromStream()
LoadImageFromStream() takes a memory stream to the bytes we loaded with GetImageData() and create a BitmapImage object from it. This object can then later be assigned as a source to any Image element we have in our XAML user interface.
Conclusion
I have shown how you can expand on the functionality of Fast video cataloger with web API. In this example we used TMDB but there are tons of other web APIs that might be useful and my hope is that this sample will make it easier for you to get started.