Product Engineer, CTO & a Beer Enthusiast
Experiments, thoughts and scripts documented for posterity.
Jun, 2014
The whole idea behind Project Frame was to provide the user the ability to download a part of the video, basically a online video clipper.
ffmpeg -i 1.mov -i 2.mov -i 3.mov -i 4.mov -filter_complex "[0:0]pad=iw*2:ih*2[a],[a][1:0]overlay=w[b],[b][2:0]overlay=0:h[c],[c][3:0]overlay=w:h" -shortest output.mp4
FFMpeg script code to resize the video:
ffmpeg -i output.mp4 -s 720x480 -acodec copy output.mp4[webm]
![]() |
Move along nothing fancy here. Connect API was used to search videos and jQuery Wookmark in combination with ImageLoader was used to display the result in pinterest style fashion. |
var webClient = new WebClient();
if (!string.IsNullOrEmpty(videoUrl))
await webClient.DownloadFileTaskAsync(videoUrl, fileName);
else
throw new Exception("No video file found to download");
private Task GenerateThumbnails(string id, string videoFileLocation)
{
var tcs = new TaskCompletionSource();
var ffmpegFile = ConfigurationManager.AppSettings["ffmpeg"];
var thumbLocation = System.Web.HttpContext.Current.Server.MapPath("~/public/thumbs");
var folderName = string.Format("{0}\\{1}", thumbLocation, id);
if (!Directory.Exists(folderName))
Directory.CreateDirectory(folderName);
var arguments = string.Format("-i {0} -f image2 -vf fps=fps=1 -s 96x72 {1}\\out%d.jpg", videoFileLocation, folderName);
var process = new Process
{
StartInfo = { FileName = ffmpegFile, Arguments = arguments },
EnableRaisingEvents = true
};
process.Exited += (sender, args) => tcs.SetResult(true);
process.Start();
return tcs.Task;
}
![]() |
This generates thumbnails of 96x72 dimensions and with files as out{number}.jpg. Folder structure something like the following: |
[HttpGet]
public HttpResponseMessage GetImageDetail(string id)
{
_sb.AppendFormat(imageInfo.Urls.Thumb, imageInfo.Caption);
_sb.AppendFormat(_pivotFormat, "Caption", imageInfo.Caption ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Date Created", imageInfo.DateCreated.ToString("F"));
_sb.AppendFormat(_pivotFormat, "Artist", imageInfo.FilmMaker ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Asset Family", imageInfo.AssetFamily ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Era", imageInfo.Era ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Keywords", string.Join(", ", imageInfo.Keywords.Select(s => s.Text).ToList()));
_sb.AppendFormat(_pivotFormat, "Clip Length", imageInfo.ClipLength ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Copyright", imageInfo.Copyright ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Collection Name", imageInfo.CollectionName ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Color Type", imageInfo.Color ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Mastered To", imageInfo.MasteredTo ?? string.Empty);
_sb.AppendFormat(_pivotFormat, "Camera Type", imageInfo.OriginallyShotOn ?? string.Empty);
private Task ClipVideo(string fileName, string outputName, int startSecond, int duration)
{
var tcs = new TaskCompletionSource();
var ffmpegFile = ConfigurationManager.AppSettings["ffmpeg"];
var clipLocation = System.Web.HttpContext.Current.Server.MapPath("~/public/clip");
var videoLocation = System.Web.HttpContext.Current.Server.MapPath("~/public/downloads");
var arguments = string.Format("-sameq -ss {0} -t {1} -i {2} {3}", startSecond, duration, string.Format("{0}\\{1}", videoLocation, fileName),
string.Format("{0}\\{1}", clipLocation, outputName));
var process = new Process
{
StartInfo = { FileName = ffmpegFile, Arguments = arguments },
EnableRaisingEvents = true
};
process.Exited += (sender, args) => tcs.SetResult(true);
process.Start();
return tcs.Task;
}