nystudio107 / craft-transcoder

Transcode video & audio files to various formats, and provide video thumbnails
https://nystudio107.com/plugins/transcoder
Other
43 stars 12 forks source link

WebM generates an empty video file, H264 works as expected. #72

Closed benfeather closed 4 months ago

benfeather commented 4 months ago

Describe the bug

I'm using the transcoder plugin inside of a custom Craft module.

The plugin produces an empty video file when I transcode a video using the default WebM config. However, if I use the default h264 config, the plugin works as expected.

Here is a cut-down version of the module:

public function actionIndex()
{
    $id = Craft::$app->request->get('id');

    if (!$id) {
        throw new \Exception('ID parameter is required.');
    }

    $asset = Asset::find()->id($id)->one();

    if (!$asset) {
        throw new \Exception("Asset matching ID '{$id}' not found.");
    }

    $transcoder = Craft::$app->plugins->getPlugin('transcoder');

    if (!$transcoder || !($transcoder instanceof Transcoder)) {
        throw new \Exception('Transcoder plugin not found.');
    }

    $url = $transcoder->transcode->getVideoUrl($asset, [
        'videoEncoder' => 'webm',
    ]);

    return $this->asJson([
        'src' => $url,
    ]);
}

If I manually run FFMPEG inside the ddev container, the video is transcoded to WebM as expected, so I don't believe FFMPEG is the issue.

Expected behaviour

A WebM version of the video asset is to be generated.

Versions

khalwat commented 4 months ago

Show me the command line you used that did generate a .webm properly for you on your setup?

benfeather commented 4 months ago

Here's the command: ffmpeg -i Input.mp4 -c:v libvpx -c:a libvorbis -quality good -cpu-used 0 Output.webm

khalwat commented 4 months ago

And what is the command that Transcoder is outputting when you try to use it? It should be in your config/logs/web.log assuming devMode is on.

benfeather commented 4 months ago

Here's the command that gets logged:

/usr/bin/ffmpeg -i '/var/www/html/web/uploads/videos/Racewell-Sheep-Handler/Dagging.mp4' -vcodec libvpx -quality good -cpu-used 0 -bufsize 1000k -threads 0 -vf "scale=300:240,unsharp=5:5:1.0:5:5:0.0" -c:a copy -f webm -y '/var/www/html/web/transcoder/video/Racewell-Sheep-Handler/Dagging_300w_240h.webm'

If I run that command, I get this error:

"Rate control parameters set without a bitrate. Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height"

I haven't modified the transcoder.php config file, so it should use the default values.

khalwat commented 4 months ago

The default parameters that are in Transcoder definitely worked at one point for webm -- my guess is that something (whether ffmpeg itself, or the libvpx codex) changed in the interim.

The major different I can see between the command that worked, and the one that did not is the audio codec setting: -c:a copy is used as a default in Transcoder, and your example is explicitly using -c:a libvorbis

benfeather commented 4 months ago

If you remove -bufsize 1000k, the command throws a different error:

Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM. Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument Error initializing output stream 0:0 --

If you swap -c:a copy with -c:a libvorbis or -c:a libopus the conversion succeeds.

/usr/bin/ffmpeg \
    -i '/var/www/html/web/uploads/videos/Racewell-Sheep-Handler/Dagging.mp4' \
    -c:v libvpx \
    -c:a libvorbis \
    -quality good \
    -cpu-used 0 \
    -threads 0 \
    -vf "scale=300:240,unsharp=5:5:1.0:5:5:0.0" \
    -f webm \
    -y \
    '/var/www/html/web/transcoder/video/Racewell-Sheep-Handler/Dagging_300w_240h.webm'
benfeather commented 4 months ago

I tried the command with -bufsize 1000k and -b:v 2M, and it worked. Looks like you have to set the target average bitrate for the bufsize flag to work.

I don't know what a reasonable default would be.

https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate

khalwat commented 4 months ago

Maybe best to just remove the -bufsize flag entirely then, and let ffmpeg figure it out.

My guess is the reason why copy doesn't work is the encoding on the audio track is such that isn't supported in webm somehow.

In any event, glad you got it working!

benfeather commented 4 months ago

It looks like the -bufsize flag is hardcoded into the FFmpeg command:

Transcode.php, line 131 CleanShot 2024-02-27 at 09 09 36@2x

Is that something you could remove? Or is there a way I can override it?