soluble-io/soluble-mediatools

Last frame thumbnail

Glagan opened this issue · 6 comments

Hi, I am trying to take a thumbnail of the last frame of a video, so I am using the makeThumbnail function, with ->withTime($video->getDuration()) on the params, but it fail silently.

I tried to find if the duration was good, but I don't really know... if I use ffprobe myself I do have the same value 113.593000 (the value I used), but in the first stream there is a duration of 113.540000, the audio stream is 113.592993 long, and in Firefox and I use video.duration I have a value of 113.592022 (113.593 in Chrome).

If I lower the original duration (113.593000) by 150ms it works. I don't really know what to do here, and what duration I should use. Thanks.

@Glagan, thanks for the clear explanation.

You are absolutely right the command is actually choosing one frame from the time given (which means we already are at the end, next frame is nothing)...

This call to ffmpeg will

$ ffmpeg -ss 0:01:01.533 -y -i './tests/data/big_buck_bunny_low.m4v' -frames:v 1 -qscale:v 2 -y './tests/tmp/testThumbAtVideoDuration.jpg'

outputs something like

frame=    0 fps=0.0 q=0.0 Lsize=N/A time=00:00:00.00 bitrate=N/A speed=   0x    
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)

Without even throwing an error, just the notice 'Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)'.

I'm currently looking at some possibilities. First of all, I'm wondering if an "out of range" thumbnail should throw an exception ? What's your idea ?

Second, I'm currently looking to add support for last frame selection. I'll find something very soon, just need to find what's the most appropriate approach.

Thanks for reporting !

I don't know if it should throw an exception, maybe follow the same "flow" as for "out of range" error, but I don't know if there is any other error of this type in the library.
Maybe use the last frame if the time parameter is higher than the duration ?

@Glagan

maybe follow the same "flow" as for "out of range" error,

Implemented an exception in #17 ;) Will be better.

Maybe use the last frame if the time parameter is higher than the duration ?

I finally have have good results with the select filter from ffmpeg (allows me to work on frame level instead of time, and it looks the way to go, at least the ffmpeg way)

The thing is that it won't be so sexy ;) For the last frame you'll need to know the total frames minus one, then appy the select filter....

Of course I'll try to make the API able to do hide this complexity... What do you think about this :

->withFrame($video->getNbFrames() - 1)

Behind the scenes I'll do something like below (u don't have to read ;)

$nbFrames = $this->infoService->getInfo($this->videoFile)->getNbFrames();

$selectFilter = new class($nbFrames - 1) implements FFMpegVideoFilterInterface {
   private $selectedFrame;
   function __construct($selectedFrame) {
       $this->selectedFrames = $selectedFrame;
   }
   public function getFFmpegCLIValue(): string
   {
       return "\"select=eq(n\,{$this->selectedFrame})\"";
   }
};

$this->thumbService->makeThumbnail(
   $this->videoFile,
   $outputFile,
   (new VideoThumbParams())->withTime(
       0
   )->withVideoFilter($selectFilter)
);
ffmpeg -y -i './tests/data/big_buck_bunny_low.m4v' -frames:v 1 -filter:v 'select=eq(n\,1112)' -qscale:v 2 -y './tests/tmp/testThumbWithFrameSelection.jpg'

So if ->withFrame($video->getNbFrames() - 1) looks good to u, can be ready tomorrow morning ;)

Yes, I searched to work with frames rather than time too and found the same solution :) Looks good, thanks.

Hey Glagan,

Just released 0.8.2 with the frame selection... I could not regenerate the doc website, I'll do it later but have a look to the markdown:

https://github.com/soluble-io/soluble-mediatools/blob/master/docs/video-thumb-service.md#recipes

Tell me if it works and thanks ;)

It works, thank you 👍