Lädt...

PHP FFmpeg Video Streaming

Komplette Video-Streaming-Lösung mit DASH- und HLS-Unterstützung, DRM-Verschlüsselung und Cloud-Speicher-Integration

Streaming-fähig

DASH & HLS mit adaptiver Bitrate

Einführung

PHP FFmpeg Video Streaming ist ein umfassender Wrapper um PHP-FFMpeg, der FFmpeg nutzt, um Medienpakete zu erstellen, die mit Online-Streaming-Protokollen wie DASH (Dynamic Adaptive Streaming over HTTP) und HLS (HTTP Live Streaming) kompatibel sind.

Adaptives Streaming

Erstellen Sie DASH- und HLS-Streams mit mehreren Bitraten-Repräsentationen

DRM-Unterstützung

AES-128-Verschlüsselung für HLS mit Schlüsselrotationsoptionen

Cloud-Integration

Direkte Integration mit S3, Google Cloud, Azure und mehr

Live-Streaming

Unterstützung für Live-Streaming von Webcams und Bildschirmaufnahmen

Anforderungen

1. FFMpeg

Diese Bibliothek erfordert eine funktionierende FFmpeg-Installation, einschließlich der Binärdateien von FFMpeg und FFProbe.

Windows-Nutzer: Für die Binärerkennung unter Windows stellen Sie sicher, dass die FFmpeg- und FFProbe-Pfade zu Ihrer Systempfad-Umgebungsvariable hinzugefügt werden.

2. PHP

Kompatibilität: Diese Bibliothek ist nur mit PHP 8.2 oder höher kompatibel.

Installation

Paketinstallation

Mit Composer:

composer require aminyazdanpanah/php-ffmpeg-video-streaming

Alternativ können Sie die Abhängigkeit zu Ihrer composer.json-Datei hinzufügen:

{
    "require": {
        "aminyazdanpanah/php-ffmpeg-video-streaming": "^1.2"
    }
}
Möchten Sie eine OTT-Plattform bauen? Die Basisversion hat alles, was Sie brauchen. Online-Demo Jetzt kaufen

Konfiguration

Dieses Paket erkennt FFmpeg- und FFprobe-Binärdateien automatisch. Wenn Sie Binärpfade explizit angeben möchten, können Sie ein Array als Konfiguration übergeben. Eine Psr\Logger\LoggerInterface kann auch übergeben werden, um Binärausführungen zu protokollieren.

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

$config = [
    'ffmpeg.binaries'  => '/usr/bin/ffmpeg',
    'ffprobe.binaries' => '/usr/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('/var/log/ffmpeg-streaming.log'));

$ffmpeg = FFMpeg::create($config, $log);

Verwendung

Bibliothek importieren

require 'vendor/autoload.php'; // path to the autoload file

Eine Ressource öffnen

Es gibt mehrere Möglichkeiten, eine Medienressource zu öffnen:

1. Lokale Datei oder unterstützte Ressource

$video = $ffmpeg->open('/var/media/video.mp4');

Für entfernte Ressourcen:

$video = $ffmpeg->open('https://www.quasarstream.com/?path/to/video.mp4');
Weitere Informationen finden Sie in der FFmpeg-Protokoll-Dokumentation für eine Liste der unterstützten Ressourcen (http, ftp, usw.).

2. Cloud-Speicher

$video = $ffmpeg->openFromCloud($from_google_cloud);
Besuchen Sie den bereitgestellten Link für Beispiele zum Zugriff auf Dateien von Amazon S3, Google Cloud Storage, Microsoft Azure Storage und benutzerdefinierten Cloud-Speicherlösungen.

3. Live-Streaming von Webcam oder Bildschirm

$capture = $ffmpeg->capture("CAMERA NAME OR SCREEN NAME");
HINWEIS: Konsultieren Sie die FFmpeg-Dokumentation für die Aufnahme von Webcams und Desktops.

DASH (Dynamic Adaptive Streaming over HTTP)

Dynamic Adaptive Streaming over HTTP (DASH), auch bekannt als MPEG-DASH, ermöglicht hochwertiges Streaming über das Internet, indem Inhalte in kurze HTTP-basierte Datei-Downloads segmentiert werden.

DASH-Dateien erstellen

Die Bibliothek generiert automatisch Manifest (MPD)- und Segmentdateien:

$video->dash()
        ->setAdaption('id=0,streams=v id=1,streams=a')
        ->x264()
        ->autoGenerateRepresentations()
        ->save();

Repräsentationen manuell generieren

use Streaming\Representation;

$r_144p  = (new Representation)->setKiloBitrate(95)->setResize(256, 144);
$r_240p  = (new Representation)->setKiloBitrate(150)->setResize(426, 240);
$r_360p  = (new Representation)->setKiloBitrate(276)->setResize(640, 360);
$r_480p  = (new Representation)->setKiloBitrate(750)->setResize(854, 480);
$r_720p  = (new Representation)->setKiloBitrate(2048)->setResize(1280, 720);
$r_1080p = (new Representation)->setKiloBitrate(4096)->setResize(1920, 1080);

$video->dash()
    ->setSegDuration(30)
    ->setAdaption('id=0,streams=v id=1,streams=a')
    ->x264()
    ->addRepresentations([$r_144p, $r_240p, $r_360p, $r_480p, $r_720p, $r_1080p])
    ->save('/var/media/dash-stream.mpd');

DASH von Kamera/Bildschirm

$r_240p = (new Representation)->setKiloBitrate(150)->setResize(426, 240);
$r_360p = (new Representation)->setKiloBitrate(276)->setResize(640, 360);

$capture->dash()
    ->setAdaption('id=0,streams=v id=1,streams=a')
    ->x264()
    ->addRepresentations([$r_240p, $r_360p])
    ->save('/var/media/dash-stream.mpd');
Hinweis: Die Methode autoGenerateRepresentations() kann nicht für kamerabasierte Medien verwendet werden.

HLS (HTTP Live Streaming)

HTTP Live Streaming (HLS) ist ein adaptives Bitraten-Streaming-Protokoll, das HTTP-basierte Datei-Downloads und M3U-Playlists verwendet.

HLS-Dateien erstellen

Um HLS-Dateien zu erstellen, verwenden Sie die <code class="inline-code">hls</code>-Instanz und geben Sie den Ausgabedateinamen an:

$video->hls()
    ->x264()
    ->autoGenerateRepresentations([720, 360])
    ->save();

Manuelle Repräsentationen

Um die genaue Kilobit-Rate und Größe für jeden Stream festzulegen, erstellen Sie manuell Representation-Objekte und fügen Sie sie der dash- oder hls-Instanz hinzu:

$r_360p = (new Representation)->setKiloBitrate(276)->setResize(640, 360);
$r_480p = (new Representation)->setKiloBitrate(750)->setResize(854, 480);
$r_720p = (new Representation)->setKiloBitrate(2048)->setResize(1280, 720);

$video->hls()
    ->setHlsBaseUrl('https://bucket.s3-us-west-1.amazonaws.com/videos')
    ->setHlsTime(5)
    ->setHlsAllowCache(false)
    ->x264()
    ->addRepresentations([$r_360p, $r_480p, $r_720p])
    ->save();

Fragmentiertes MP4

Für das fragmentierte MP4-Format in HLS verwenden Sie die <code class="inline-code">fragmentedMP4</code>-Methode:

$video->hls()
    ->fragmentedMP4()
    ->x264()
    ->autoGenerateRepresentations([720, 360])
    ->save();

HLS-Live-Streaming

Für Live-Streaming von einer Kamera oder einem Bildschirm verwenden Sie die <code class="inline-code">hls</code>-Instanz und geben Sie den Ausgabedateinamen an:

$r_480p = (new Representation)->setKiloBitrate(750)->setResize(854, 480);

$capture->hls()
    ->setHlsListSize(10) // Delete this line if you want to save video after live streaming
    ->setFlags([\Streaming\HLSFlag::DELETE_SEGMENTS]) // Delete this line if you want to save video after live streaming
    ->x264()
    ->addRepresentation($r_480p)
    ->save('/var/media/hls-stream.m3u8');
Hinweis: Die Methode autoGenerateRepresentations() kann nicht für kamerabasierte Medien verwendet werden. HEVC- und VP9-Formate werden für HLS-Packaging nicht unterstützt, es sei denn, Sie verwenden fragmentiertes MP4.

Verschlüsselung (DRM)

HLS-Verschlüsselung verwendet den Advanced Encryption Standard (AES) im Cipher Block Chaining (CBC)-Modus. Das bedeutet, dass jeder Block mit dem Chiffriertext des vorherigen Blocks verschlüsselt wird. Mehr erfahren

Verschlüsselungsschlüssel generieren

  • Pfad: Geben Sie einen Pfad an, um eine zufällige Schlüsseldatei auf Ihrem lokalen Computer zu speichern
  • URL: Geben Sie eine URL (oder einen Pfad) auf Ihrer Website an, über die auf die Schlüsseldatei zugegriffen werden kann

Verschlüsselung mit einem einzigen Schlüssel

Der folgende Code generiert einen einzigen Schlüssel für alle Segmente:

//A path you want to save a random key to your local machine
$save_to = '/home/public_html/PATH_TO_KEY_DIRECTORY/key';

//A URL (or a path) to access the key on your website
$url = 'https://www.quasarstream.com/?PATH_TO_KEY_DIRECTORY/key';
// or $url = '/PATH_TO_KEY_DIRECTORY/random_key.key';

$video->hls()
    ->encryption($save_to, $url)
    ->x264()
    ->autoGenerateRepresentations([1080, 480, 240])
    ->save('/var/media/hls-stream.m3u8');

Schlüsselrotation

Sie können die Verschlüsselungsschlüssel optional regelmäßig rotieren, indem Sie einen "Schlüsselrotationszeitraum" an die Verschlüsselungsmethode übergeben. Dadurch wird nach einer bestimmten Anzahl von Segmenten ein neuer Schlüssel generiert:

//A path you want to save a random key to your local machine
    $save_to = '/home/public_html/PATH_TO_KEY_DIRECTORY/key';

//A URL (or a path) to access the key on your website
$url = 'https://www.quasarstream.com/?PATH_TO_KEY_DIRECTORY/key';

$video->hls()
    ->encryption($save_to, $url, 10) // New key every 10 segments
    ->x264()
    ->autoGenerateRepresentations([720, 240])
    ->save('/var/media/hls-stream.m3u8');
Einschränkungen und Alternativen: Obwohl FFmpeg AES-Verschlüsselung für HLS unterstützt, ist es keine vollständige Digital Rights Management (DRM)-Lösung. Für eine vollständige DRM-Lösung sollten Sie FairPlay Streaming, PlayReady von Microsoft oder Widevine von Google in Betracht ziehen.

Ihre Schlüssel schützen

Es ist entscheidend, Ihre Verschlüsselungsschlüssel auf Ihrer Website zu sichern:

  • Token-basierte Zugriffskontrolle: Verwenden Sie Tokens über GET-/POST-Methoden oder Autorisierungs-Header
  • Sitzungs- oder Cookie-basierte Zugriffskontrolle: Implementieren Sie eine Sitzungsverwaltung, um den Zugriff zu beschränken

Untertitel

Sie können Untertitel zu HLS-Streams hinzufügen, indem Sie die subtitle-Methode verwenden:

use Streaming\HLSSubtitle;

$persian = new HLSSubtitle('/var/subtitles/subtitles_fa.vtt', 'فارسی', 'fa');
$persian->default();
$english = new HLSSubtitle('/var/subtitles/subtitles_en.vtt', 'english', 'en');
$german  = new HLSSubtitle('/var/subtitles/subtitles_de.vtt', 'Deutsch', 'de');
$chinese = new HLSSubtitle('/var/subtitles/subtitles_zh.vtt', '中文', 'zh');
$spanish = new HLSSubtitle('/var/subtitles/subtitles_es.vtt', 'Español', 'es');

$video->hls()
    ->subtitles([$persian, $english, $german, $chinese, $spanish])
    ->x264()
    ->autoGenerateRepresentations([1080, 720])
    ->save('/var/media/hls-stream.m3u8');
Hinweis: Alle m3u8-Dateien werden nach den Regeln des RFC 8216 generiert. Vorerst sind nur WebVTT-Dateien akzeptabel.

Transkodierungsüberwachung

Ein Format kann FFMpeg\Format\ProgressableInterface erweitern, um Echtzeit-Informationen über den Transkodierungsprozess zu erhalten:

$format = new Streaming\Format\X264();
$start_time = 0;

$percentage_to_time_left = function ($percentage) use (&$start_time) {
    if($start_time === 0){
        $start_time = time();
        return "Calculating...";
    }

    $diff_time = time() - $start_time;
    $seconds_left = 100 * $diff_time / $percentage - $diff_time;

    return gmdate("H:i:s", $seconds_left);
};

$format->on('progress', function ($video, $format, $percentage) use($percentage_to_time_left) {
    // You can update a field in your database or log it to a file
    // You can also create a socket connection and show a progress bar to users
    echo sprintf("\rTranscoding...(%s%%) %s [%s%s]",
        $percentage,
        $percentage_to_time_left($percentage),
        str_repeat('#', $percentage),
        str_repeat('-', (100 - $percentage))
    );
});

$video->dash()
    ->setFormat($format)
    ->autoGenerateRepresentations()
    ->setAdaption('id=0,streams=v id=1,streams=a')
    ->save();

Ausgabeoptionen

1. Lokaler Pfad

Sie können den Ausgabeort festlegen, indem Sie einen lokalen Pfad übergeben. Wenn das Verzeichnis nicht existiert, erstellt die Bibliothek es automatisch:

$dash = $video->dash()
    ->x264()
    ->autoGenerateRepresentations()
    ->setAdaption('id=0,streams=v id=1,streams=a');

$dash->save('/var/media/dash/test.mpd');

Wenn Sie den save-Parameter weglassen, werden die Dateien im selben Verzeichnis wie die Eingabedatei gespeichert:

$hls = $video->hls()
    ->x264()
    ->autoGenerateRepresentations();

$hls->save();
Wichtig: Wenn Sie eine Datei aus dem Cloud-Speicher öffnen, ohne einen lokalen Pfad anzugeben, müssen Sie einen Ausgabepfad mit save() bereitstellen.

2. Cloud-Speicher (nur VOD)

Speichern Sie gepackte Dateien direkt in Cloud-Speicher-Anbietern (nur Video-on-Demand):

$dash->save(null, [$to_aws_cloud]);
$hls->save('/var/media/hls.m3u8', [$to_google_cloud, $to_custom_cloud]);

Video-Transkodierungs-Workflow

Eine Illustration des End-to-End-Prozesses.

Input Video File
Output Transcoded File

Eingabequelle

Cloud

Lokal

Transkodierung

HLS
DASH

Ausgabe

Cloud

Lokal

Besuchen Sie den bereitgestellten Link für Beispiele zum Zugriff auf Dateien von Amazon S3, Google Cloud Storage, Microsoft Azure Storage und benutzerdefinierten Cloud-Speicherlösungen.

3. Auf einen Server hochladen (Live-Streaming)

Laden Sie segmentierte Dateien hoch und aktualisieren Sie Manifestdateien direkt auf einem HTTP-Server:

// DASH
$dash->live('http://YOUR-WEBSITE.COM/live-stream/out.mpd');

// HLS
$hls->setMasterPlaylist('/var/media/live-master-manifest.m3u8')
    ->live('http://YOUR-WEBSITE.COM/live-stream/out.m3u8');

Metadaten extrahieren

Informationen aus Multimedia-Streams und Videodateien abrufen:

$hls = $hls->save();
$metadata = $hls->metadata();

print_r($metadata->get()); // print an array
$metadata->saveAsJson('path/to/meta.json'); // save metadata as JSON

var_dump($metadata->getVideoStreams()); // StreamCollection object
var_dump($metadata->getFormat()); // Format object
echo gmdate("H:i:s", intval($metadata->getFormat()->get('duration'))); // duration

Stream-Konvertierung

Konvertieren Sie zwischen verschiedenen Streaming-Formaten, indem Sie eine Manifest-URL an die input-Methode übergeben:

HLS zu DASH

$stream = $ffmpeg->open('https://www.quasarstream.com/?PATH/TO/HLS-MANIFEST.M3U8');

$stream->dash()
    ->x264()
    ->addRepresentations([$r_360p, $r_480p])
    ->save('/var/media/dash-stream.mpd');

DASH zu HLS

$stream = $ffmpeg->open('https://www.quasarstream.com/?PATH/TO/DASH-MANIFEST.MPD');

$stream->hls()
    ->x264()
    ->autoGenerateRepresentations([720, 360])
    ->save('/var/media/hls-stream.m3u8');

Stream zu Datei

$format = new Streaming\Format\X264();
$format->on('progress', function ($video, $format, $percentage){
    echo sprintf("\rTranscoding...(%s%%) [%s%s]",
        $percentage,
        str_repeat('#', $percentage),
        str_repeat('-', (100 - $percentage))
    );
});

$stream->stream2file()
    ->setFormat($format)
    ->save('/var/media/new-video.mp4');

Erweiterte Funktionen

Sie können andere erweiterte Funktionen der PHP-FFMpeg-Bibliothek nutzen. Die open-Methode enthält das Media-Objekt von PHP-FFMpeg:

Bilder extrahieren

Einen Frame zu einem beliebigen Zeitpunkt extrahieren:

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

GIFs erstellen

Animierte Bilder aus Videosequenzen erstellen:

$video->gif(
        FFMpeg\Coordinate\TimeCode::fromSeconds(2),
        new FFMpeg\Coordinate\Dimension(640, 480),
        3 // duration in seconds
    )
        ->save('/var/media/animated_image.gif');

Asynchrone Aufgabenausführung

Für Produktionsumgebungen sollten Sie die Packaging-Prozesse im Hintergrund ausführen:

  • Symfony Console Component: Erstellen Sie Befehlszeilenbefehle für Cronjobs und Batch-Verarbeitung
  • Laravel Queues: Leiten Sie Jobs zur Verarbeitung an Hintergrund-Queues weiter
  • Benutzerdefinierte Skripte: Erstellen Sie Skripte mit crontab für die geplante Verarbeitung

Open-Source-Player

Empfohlene Open-Source-Player für die Wiedergabe von gepackten Videos:

Web-Player

DASH- und HLS-Unterstützung

Nur DASH

Nur HLS

Mobile und Desktop-Player

Plattform Player Unterstützte Formate
Android AndroidX Media DASH & HLS
iOS Native Player HLS
Windows/Linux/macOS FFmpeg (ffplay), VLC media player DASH & HLS
Wichtige Hinweise:
  • Übergeben Sie immer die URL der Master-Playlist (Manifest) an die Player
  • Wenn Sie Stream-Inhalte in der Cloud speichern, stellen Sie sicher, dass der Inhaltslink öffentlich ist
  • iOS hat keine native Unterstützung für DASH. Bibliotheken wie Viblast und MPEGDASH-iOS-Player existieren, aber die Kompatibilität kann variieren

Unterstützen Sie uns

Wenn Sie dieses Projekt nützlich finden, unterstützen Sie uns bitte: