0

I'm just learning how to use ffmpeg a few hours ago to generate video thumbnails.

These are some results:

1

2

I'd used the same size (width - height) to Youtube's. Each image contains max 25 thumbnails (5x5) with the size 160x90.

Everything looks good until:

public async Task GetVideoThumbnailsAsync(string videoPath, string videoId)
{
    byte thumbnailWidth = 160;
    byte thumbnailHeight = 90;

    string fps = "1/2";

    videoPath = Path.Combine(_environment.WebRootPath, videoPath);

    string videoThumbnailsPath = Path.Combine(_environment.WebRootPath, $"assets/images/video_thumbnails/{videoId}");
    string outputImagePath = Path.Combine(videoThumbnailsPath, "item_%d.jpg");

    Directory.CreateDirectory(videoThumbnailsPath);

    using (var ffmpeg = new Process())
    {
        ffmpeg.StartInfo.Arguments = $" -i {videoPath} -vf fps={fps} -s {thumbnailWidth}x{thumbnailHeight} {outputImagePath}";
        ffmpeg.StartInfo.FileName = Path.Combine(_environment.ContentRootPath, "FFmpeg/ffmpeg.exe");
        ffmpeg.Start();
    }

    await Task.Delay(3000);

    await GenerateThumbnailsAsync(videoThumbnailsPath, videoId);
}

I'm getting a trouble with the line:

await Task.Delay(3000);

When I learn the way to use ffmpeg, they didn't mention about it. After some hours failed, I notice that:

An mp4 video (1 min 31 sec - 1.93Mb) requires some delay time ~1000ms. And other, an mp4 video (1 min 49 sec - 7.25Mb) requires some delay time ~3000ms.

If I don't use Task.Delay and try to get all the files immediately, it would return 0 (there was no file in the directory).

Plus, each file which has a difference length to the others requires a difference delay time. I don't know how to calculate it.

And my question is: How to check when the task has completed?

P/s: I don't mean to relate to javascript, but in js, there is something called Promise:

var promise = new Promise(function (done) {
    var todo = function () {
        done();
    };

    todo();
});

promise.then(function () {
    console.log('DONE...');
});

I want to edit the code like that.

Thank you!

  • I'm not familiar with ffmpeg, but C# has [events](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/). I suspect if you look at the ffmpeg documentation, there are some events that you can subscribe to that are raised when the process completes. – Lews Therin May 25 '18 at 19:06
  • 1
    This answer: https://stackoverflow.com/a/19104345/393701 might be of interest to you. – SirDarius May 25 '18 at 19:07
  • 1
    In c#, analog of Promise is Task, and this specific use of Promise can be achieved with TaskCompletionSource. – Evk May 25 '18 at 19:19
  • @SirDarius Perfect! I have tried again with the advice and it's working good. Thank you so much! –  May 25 '18 at 19:22

1 Answers1

0

If you want to do it synchronously, then you could call ffmpeg.WaitForExit(), which will cause the line to wait until the process has finished. Otherwise you'll need to start a Task to run it in the background. A C# Task is somewhat similar to a Promise in JavaScript.

This answer can also be used for details on how to wrap WaitForExit so that you can use it with an await

keithwill
  • 1,964
  • 1
  • 17
  • 26