laravel-ffmpeg icon indicating copy to clipboard operation
laravel-ffmpeg copied to clipboard

fix: Remove EXT-X-ENDLIST from master playlist file

Open dave-nicholas opened this issue 1 year ago • 2 comments

I am a contributor on the shaka project and noticed that playback was broken with this library. This PR fixes a bug in the master playlist and allows playback with shaka (and probably other players where playback previously failed).

Unlike the EXTM3U element which is required at the start every Media Playlist and every Master Playlist. The EXT-X-ENDLIST should only appear in a Media Playlist file.

dave-nicholas avatar Feb 04 '24 01:02 dave-nicholas

Yeah EXT-X-ENDLIST line causes shaka player to throw error

exxsy avatar Jun 17 '24 21:06 exxsy

If you just dont want to wait PR,

Create a PlaylistGenerator for this case, like this one.

namespace App\PlaylistGenerators;

class HLSExtendedGenerator implements PlaylistGenerator
{
    public const PLAYLIST_START = '#EXTM3U';

    private function getStreamInfoLine(Media $segmentPlaylistMedia, string $key): string
    {
        $segmentPlaylist = $segmentPlaylistMedia->getDisk()->get(
            $segmentPlaylistMedia->getDirectory() . HLSExporter::generateTemporarySegmentPlaylistFilename($key)
        );

        $lines = DynamicHLSPlaylist::parseLines($segmentPlaylist)->filter();

        return $lines->get($lines->search($segmentPlaylistMedia->getFilename()) - 1);
    }

    public function get(array $segmentPlaylists, PHPFFMpeg $driver): string
    {
        return Collection::make($segmentPlaylists)->map(function (Media $segmentPlaylist, $key) use ($driver) {
            $streamInfoLine = $this->getStreamInfoLine($segmentPlaylist, $key);

            $media = (new MediaOpener($segmentPlaylist->getDisk(), $driver))
                ->openWithInputOptions($segmentPlaylist->getPath(), ['-allowed_extensions', 'ALL']);

            if ($media->getVideoStream()) {
                if ($frameRate = StreamParser::new($media->getVideoStream())->getFrameRate()) {
                    $streamInfoLine .= ",FRAME-RATE={$frameRate}";
                }
            }

            return [$streamInfoLine, $segmentPlaylist->getFilename()];
        })->collapse()->prepend(self::PLAYLIST_START)->implode(PHP_EOL);
    }
}

Then use it like this,

        FFMpeg::fromDisk("videos")
            ->open("/$this->name.$this->extension")
            ->exportForHLS()
            ->withPlaylistGenerator(new HLSExtendedGenerator)
            ->setSegmentLength(10)->...

exxsy avatar Jun 17 '24 22:06 exxsy

Could this please be merged? I've got the same issue on a new project, and using this package.

@exxsy Thanks for the workaround. It's basically a copy of the current one without the line finish. I would suggest also making those methods/vars protected instead of private. This would make it easier to simple extend the current one, and overrule what's needed. :)

francoism90 avatar Jan 17 '25 13:01 francoism90

@francoism90 since it was a workaround and temporary, i didnt think that much. You're welcome. Happy coding

exxsy avatar Jan 17 '25 19:01 exxsy

@exxsy This was more a comment for upstream. :)

I'll try to make a PR with this change.

francoism90 avatar Jan 17 '25 19:01 francoism90

Hello, Thanks @protonemedia for this awesome package! Any plans to merge this PR?

nagi1 avatar Mar 25 '25 10:03 nagi1

I created a fork with all open PRs merged until @pascalbaljet or @protonemedia merge them. https://github.com/nagi1/laravel-ffmpeg

Thanks For this awesome package really appreciated!

nagi1 avatar Mar 25 '25 10:03 nagi1

I've made it optional because I find it too risky to remove it by default, as we have never had problems with it.

FFMpeg::fromDisk("videos")
    ->open("/$this->name.$this->extension")
    ->exportForHLS()
    ->withoutPlaylistEndLine()

pascalbaljet avatar Apr 01 '25 20:04 pascalbaljet

@pascalbaljet Just to confirm it works! :)

francoism90 avatar Jul 06 '25 12:07 francoism90