quasarstream / PHP-FFmpeg-video-streaming

📼 Package media content for online streaming(DASH and HLS) using FFmpeg
https://www.quasarstream.com/op/php/ffmpeg-streaming?u=php-ff
MIT License
514 stars 117 forks source link

Grabbing frame from video crashes #69

Closed ffd8 closed 4 years ago

ffd8 commented 4 years ago

Describe the bug Attempt to save a $video->frame() failes while using this library. If it's not importanted and the base PHP-FFMpeg library is used, it works.

To Reproduce

$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(1));
$frame->save('poster.jpg');

Expected behavior Save a single frame of the video at a given time.

Desktop/Server (please complete the following information):

Additional context When using just PHP-FFMpeg, it's no problem to grab a poster frame from the video with the following code:

$ffmpegConfig = [
    'ffmpeg.binaries'  => '/usr/local/bin/ffmpeg',
    'ffprobe.binaries' => '/usr/local/bin/ffprobe',
    'timeout'          => 3600, // The timeout for the underlying process
    'ffmpeg.threads'   => 12,   // The number of threads that FFmpeg should use
];
$ffmpeg = FFMpeg\FFMpeg::create($ffmpegConfig);
$ffprobe = FFMpeg\FFProbe::create($ffmpegConfig);

$video = $ffmpeg->open('video.mov');

// gen poster frame
$duration = $video->getStreams()->videos()->first()->get('duration');
$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds($duration/2.0));
$frame->save('poster.jpg');

Once importing and using PHP-FFmpeg-video-streaming I'm getting a 500 error for nearly the same code:

use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Streaming\FFMpeg;

$ffmpegConfig = [
    'ffmpeg.binaries'  => '/usr/local/bin/ffmpeg',
    'ffprobe.binaries' => '/usr/local/bin/ffprobe',
    'timeout'          => 3600, // The timeout for the underlying process
    'ffmpeg.threads'   => 12,   // The number of threads that FFmpeg should use
];

$log = new Logger('FFmpeg_Streaming');
$log->pushHandler(new StreamHandler('ffmpeg-streaming.log')); // path to log file
$ffmpeg = FFMpeg::create($ffmpegConfig, $log);

$video = $ffmpeg->open('video.mov');

// gen poster frame
$duration = $video->getStreams()->videos()->first()->get('duration');
$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds($duration/2.0));
$frame->save('poster.jpg');

FYI, this library worked fine for exporting HLS files based on the documentation (logging as well) – it's only when trying to grab the frame from a video.

If I disable the importing of library and revert to the PHP-FFmpeg instancing of $ffmpeg, then it works again:

// use Streaming\FFMpeg;
// $ffmpeg = FFMpeg::create($ffmpegConfig, $log);

$ffmpeg = FFMpeg\FFMpeg::create($ffmpegConfig);

Also tried using:

$ffmpeg = Streaming\FFMpeg::create($ffmpegConfig);

Edit: just added full error_reporting, and get the following error while trying to save a frame: Fatal error: Uncaught Error: Class 'Streaming\FFMpeg\Coordinate\TimeCode' not found in... (path to file) So the script is inject Streaming\ in front of the frame's FFMpeg\Coordinate\TimeCode command...

Is this a bug, or am I doing something wrong above?

ffd8 commented 4 years ago

Aha! Found a way to fix it! Was wondering how I could remove that Streaming portion of the command that was being injected (assuming it shouldn't be there) – not very familiar with how this structure works in PHP.. but added a \ infront of FFMpeg = viola, poster frame generated!

$frame = $video->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds(1));
$frame->save('poster.jpg');

Not sure if it's something to update in the docs (few times under 'Other Advanced Features') or if it's something that should be adjusted within the library to not need that \?

Same is true for the instructions for a gif, as written gave same error as frame(), but added 2x \ worked:

$video
->gif(\FFMpeg\Coordinate\TimeCode::fromSeconds(1), new \FFMpeg\Coordinate\Dimension(640, 480), 1)
->save('animated_image.gif');
aminyazdanpanah commented 4 years ago

The bug is related to some versions of PHP on Mac and Linux, In other words, PHP can not use the namespace without the backslash.

It seems like you found a solution, so I closed this issue. If you have any further questions about this issue, please post it here.