PHP code example of alexhackney / lara-nimble

1. Go to this page and download the library: Download alexhackney/lara-nimble library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

alexhackney / lara-nimble example snippets


use AlexHackney\LaraNimble\Facades\Nimble;

// List all live streams across all applications
$streams = Nimble::streams()->list();
foreach ($streams as $stream) {
    echo "{$stream->app}/{$stream->stream}\n";
    echo "  Protocol: {$stream->protocol}\n";
    echo "  Resolution: {$stream->resolution}\n";
    echo "  Codecs: {$stream->vcodec} / {$stream->acodec}\n";
    echo "  Bandwidth: " . round(($stream->bandwidth ?? 0) / 1_000_000, 2) . " Mbps\n";
    echo "  Publisher: {$stream->publisherIp}:{$stream->publisherPort}\n";
}

// Only one application
$streams = Nimble::streams()->byApp('live');

// Find one stream (null when it is not live)
$stream = Nimble::streams()->find('live', 'stream1');

// Convenience boolean
if (Nimble::streams()->exists('live', 'stream1')) {
    echo 'Stream is live!';
}

use AlexHackney\LaraNimble\DTOs\RestreamDto;
use AlexHackney\LaraNimble\Facades\Nimble;

// List republishing rules created through this API
$rules = Nimble::restream()->list();
foreach ($rules as $rule) {
    echo "Rule {$rule->id}: {$rule->srcApp}/{$rule->srcStream}";
    echo " -> {$rule->destAddr}:{$rule->destPort}/{$rule->destApp}/{$rule->destStream}\n";
}

// Get a specific rule (null when it does not exist)
$rule = Nimble::restream()->get(42);

// Create a rule from explicit fields
$created = Nimble::restream()->create(new RestreamDto(
    srcApp: 'live',
    srcStream: 'stream1',
    destAddr: 'a.rtmp.youtube.com',
    destPort: 1935,
    destApp: 'live2',
    destStream: 'your-stream-key',
));
echo "Created rule {$created->id}";

// Or decompose an RTMP(S) publishing URL, e.g. Facebook's secure_stream_url
$created = Nimble::restream()->create(RestreamDto::fromUrl(
    'live',
    'stream1',
    'rtmps://live-api-s.facebook.com:443/rtmp/your-stream-key'
));

// Delete a rule
if (Nimble::restream()->delete(42)) {
    echo "Rule deleted!";
}

// Connection statistics for all rules
foreach (Nimble::restream()->stats() as $stat) {
    echo "Rule {$stat->id}: {$stat->state}, {$stat->bandwidth} bandwidth\n";
}

use AlexHackney\LaraNimble\DTOs\RestreamDto;
use AlexHackney\LaraNimble\Facades\Nimble;

$desired = [
    RestreamDto::fromUrl('live', 'stream1', 'rtmps://live-api-s.facebook.com:443/rtmp/fb-key'),
    RestreamDto::fromUrl('live', 'stream1', 'rtmp://a.rtmp.youtube.com/live2/yt-key'),
];

$result = Nimble::restream()->sync($desired);

if ($result->changed()) {
    logger()->info('Restream rules reconciled', [
        'created' => $result->created->count(),
        'deleted' => $result->deleted->count(),
        'kept' => $result->kept->count(),
    ]);
}

use AlexHackney\LaraNimble\Facades\Nimble;

// List all active sessions
$sessions = Nimble::sessions()->list();
foreach ($sessions as $session) {
    echo "Session {$session->id}: {$session->app}/{$session->stream}\n";
    echo "  Type: {$session->type}\n";           // HLS, MPEG-DASH, ...
    echo "  Client IP: {$session->clientIp}\n";
    echo "  Bytes sent: {$session->bytesSent}\n";
}

// Find one session (null when it does not exist)
$session = Nimble::sessions()->find(4);

// Terminate one or many sessions
Nimble::sessions()->terminate(4);
Nimble::sessions()->terminate([4, 5, 6]);

use AlexHackney\LaraNimble\Facades\Nimble;

// Archive status for all DVR-enabled streams
$archives = Nimble::dvr()->status();
foreach ($archives as $archive) {
    echo "{$archive->stream}: {$archive->duration}s, {$archive->size} bytes\n";
}

// One stream, including its recorded period timeline
$archive = Nimble::dvr()->status('live', 'stream1', timeline: true)->first();
foreach ($archive->timeline as $period) {
    echo "Period {$period['period']}: {$period['start']} - {$period['end']}\n";
}

// Build a download URL for an MP4 export (auth params vr()->exportSrtUrl('live', 'stream1', start: 1700000000, end: 1700003600);
$srt = Nimble::dvr()->exportSrt('live', 'stream1', start: 1700000000, end: 1700003600, track: 1, lang: 'en');

// Reload an archive from disk
Nimble::dvr()->reload('live', 'stream1');

// Cleanup: keep only the most recent 60 minutes
Nimble::dvr()->cleanupArchive('live', 'stream1', targetDepth: 60);

// Cleanup: remove a specific range
Nimble::dvr()->cleanupArchive('live', 'stream1', from: 1700000000, to: 1700003600);

use AlexHackney\LaraNimble\Facades\Nimble;

// List active publishers
$publishers = Nimble::publishControl()->status();
foreach ($publishers as $publisher) {
    echo "{$publisher->id}: {$publisher->stream} from {$publisher->ip}\n";
}

// Disconnect publishers by id
Nimble::publishControl()->deny('pub-1');
Nimble::publishControl()->deny(['pub-1', 'pub-2']);

use AlexHackney\LaraNimble\Facades\Nimble;

// Get server status
$status = Nimble::server()->status();
echo "Connections: {$status->connections}\n";
echo "Out rate: {$status->outRate}\n";
echo "RAM cache: {$status->ramCacheSize} / {$status->maxRamCacheSize}\n";
echo "File cache: {$status->fileCacheSize} / {$status->maxFileCacheSize}\n";
// $status->sysInfo holds the raw SysInfo array as returned by Nimble

// Reload server configuration (optionally including drm.conf)
Nimble::server()->reloadConfig();
Nimble::server()->reloadConfig(drm: true);

// Reload SSL certificates without a restart
Nimble::server()->reloadSslCertificates();

// Trigger settings sync with WMSPanel
Nimble::server()->syncPanelSettings();

// Server playlist status (raw array, shape defined by Nimble)
$playlists = Nimble::server()->playlistStatus();

use AlexHackney\LaraNimble\Facades\Nimble;

// Resolve the cache key for an origin URL (null when unknown)
$key = Nimble::cache()->key('http://origin:8081/vod/sample.mp4');

// Evict cached items; returns the list of removed items
$removed = Nimble::cache()->delete($key);

// Dry run: report what would be removed without removing it
$wouldRemove = Nimble::cache()->delete($key, dryRun: true);

use AlexHackney\LaraNimble\Facades\Nimble;

$rtmp = Nimble::protocols()->rtmpSettings();       // RtmpSettings structure
$mpegts = Nimble::protocols()->mpegtsStatus();
$cameras = Nimble::protocols()->mpegtsSettings();  // CamerasHash + Cameras
$srtOut = Nimble::protocols()->srtSenderStats();   // fields per SRT spec
$srtIn = Nimble::protocols()->srtReceiverStats();
$ristOut = Nimble::protocols()->ristSenderStats(); // fields per RIST spec
$ristIn = Nimble::protocols()->ristReceiverStats();
$ndi = Nimble::protocols()->ndiList();

use AlexHackney\LaraNimble\Facades\Nimble;

// Current metadata of an Icecast stream
$info = Nimble::icecast()->info('radio', 'main');
echo $info['icy-name'] ?? '';
echo $info['streamtitle'] ?? '';

// Inject new metadata
Nimble::icecast()->updateMetadata('radio', 'main', 'Artist - Song');
Nimble::icecast()->updateMetadata('radio', 'main', 'Artist - Song', 'https://example.com');

use AlexHackney\LaraNimble\Facades\Nimble;

// Start an ad break (optionally with a duration in seconds)
Nimble::scte35()->cueOut('live', 'stream1', 30);

// End an ad break
Nimble::scte35()->cueIn('live', 'stream1');

// Insert a time_signal marker
Nimble::scte35()->timeSignal('live', 'stream1', segType: 52, upidType: 14, upid: 'abc123');



namespace App\Http\Controllers;

use AlexHackney\LaraNimble\DTOs\RestreamDto;
use AlexHackney\LaraNimble\Facades\Nimble;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class StreamController extends Controller
{
    public function index(): JsonResponse
    {
        $streams = Nimble::streams()->list();

        return response()->json([
            'streams' => $streams->map->toArray(),
        ]);
    }

    public function restream(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'stream' => ['



namespace App\Jobs;

use AlexHackney\LaraNimble\DTOs\RestreamDto;
use AlexHackney\LaraNimble\Facades\Nimble;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class CreateRestreamJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public string $srcApp,
        public string $srcStream,
        public string $targetUrl,
    ) {
    }

    public function handle(): void
    {
        Nimble::restream()->create(RestreamDto::fromUrl(
            $this->srcApp,
            $this->srcStream,
            $this->targetUrl,
        ));
    }
}

return [
    // Connection (only NIMBLE_HOST is          // Your Nimble server
    'port' => env('NIMBLE_PORT', 8082),                 // Standard Nimble API port
    'protocol' => env('NIMBLE_PROTOCOL', 'http'),       // http or https

    // Authentication (optional)
    'token' => env('NIMBLE_TOKEN'),                     // Only if server gging (for debugging)
    'log_requests' => env('NIMBLE_LOG_REQUESTS', false),
    'log_channel' => env('NIMBLE_LOG_CHANNEL', 'stack'),

    // SSL (dev only - never disable in production)
    'verify_ssl' => env('NIMBLE_VERIFY_SSL', true),
];

use AlexHackney\LaraNimble\Facades\Nimble;

public function test_it_creates_a_restream_rule(): void
{
    $fake = Nimble::fake([
        // 'METHOD /endpoint' or just '/endpoint'; * wildcards supported;
        // values are response arrays or closures
        'POST /manage/rtmp/republish' => ['status' => 'Ok', 'rule' => [
            'id' => 7,
            'src_app' => 'live',
            'src_stream' => 'stream1',
            'dest_addr' => 'live-api-s.facebook.com',
            'dest_port' => 443,
            'dest_app' => 'rtmp',
            'dest_stream' => 'fb-key',
            'ssl' => true,
        ]],
    ]);

    $this->post('/api/restreams', ['stream' => 'stream1', 'target_url' => '...'])
        ->assertCreated();

    $fake->assertRestreamCreated(fn (array $payload) => $payload['ssl'] === true);
    $fake->assertSentCount(1);
}

use AlexHackney\LaraNimble\Rules\NimbleHostRule;
use AlexHackney\LaraNimble\Rules\StreamExistsRule;
use AlexHackney\LaraNimble\Rules\StreamProtocolRule;

// Validate Nimble host connectivity
$request->validate([
    'host' => ['



namespace App\Listeners;

use AlexHackney\LaraNimble\Events\SessionTerminated;
use Illuminate\Support\Facades\Log;

class LogSessionTerminated
{
    public function handle(SessionTerminated $event): void
    {
        Log::info('Nimble session terminated', ['session_id' => $event->sessionId]);
    }
}

protected $listen = [
    \AlexHackney\LaraNimble\Events\SessionTerminated::class => [
        \App\Listeners\LogSessionTerminated::class,
    ],
];
bash
php artisan vendor:publish --provider="AlexHackney\LaraNimble\NimbleServiceProvider" --tag="nimble-config"
bash
php artisan nimble:status
bash
php artisan nimble:streams

# Only one application
php artisan nimble:streams --app=live
bash
php artisan nimble:health