PHP code example of ekstremedia / laravel-youtube

1. Go to this page and download the library: Download ekstremedia/laravel-youtube 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/ */

    

ekstremedia / laravel-youtube example snippets


use EkstreMedia\LaravelYouTube\Facades\YouTube;

// Authenticate user (redirect to Google)
return redirect()->to(YouTube::getAuthUrl());

// After authentication, upload a video
$video = YouTube::forUser(auth()->id())
    ->uploadVideo(
        '/path/to/video.mp4',
        [
            'title' => 'My Amazing Video',
            'description' => 'This is a great video!',
            'tags' => ['laravel', 'youtube', 'api'],
            'category_id' => '22',
            'privacy_status' => 'public',
        ]
    );

echo "Video uploaded: " . $video->watch_url;

// Method 1: Use the default (most recent) active token
YouTube::usingDefault()->uploadVideo($file, $metadata);

// Method 2: Use a specific channel by ID
YouTube::forChannel('UCxxxxxxxxxx')->uploadVideo($file, $metadata);

// Method 3: For legacy support, specify user ID
YouTube::forUser($userId)->uploadVideo($file, $metadata);

// In your Pi upload endpoint
use Ekstremedia\LaravelYouTube\Facades\YouTube;

Route::post('/api/pi/upload', function (Request $request) {
    $request->validate([
        'video' => 'oadVideo($file, [
        'title' => "Pi Camera {$request->camera_id} - " . now()->format('Y-m-d H:i'),
        'description' => 'Automated timelapse from Raspberry Pi',
        'tags' => ['raspberry-pi', 'timelapse', $request->camera_id],
        'privacy_status' => 'unlisted',
    ]);

    return response()->json([
        'success' => true,
        'video_id' => $video->video_id,
        'watch_url' => $video->watch_url,
    ]);
});

// config/youtube.php
'routes' => [
    'auth_page' => [
        'middleware' => ['web', 'auth'], // Default: middleware' => ['web', 'can:manage-youtube'],  // Laravel Gate
        // 'middleware' => ['web'],                         // No authentication
    ],
],

// Link to authentication page
<a href="{{ route('youtube.authorize') }}">Connect YouTube</a>

// Or use the configured path
<a href="/{{ config('youtube.routes.auth_page.path') }}">Authorize YouTube</a>

use EkstreMedia\LaravelYouTube\Services\AuthService;

$authService = app(AuthService::class);

// Generate OAuth URL with state for CSRF protection
$state = Str::random(40);
session(['youtube_oauth_state' => $state]);
$authUrl = $authService->getAuthUrl($state);

// In callback handler
if (request('state') !== session('youtube_oauth_state')) {
    abort(403, 'Invalid state');
}

// Exchange code for tokens
$tokens = $authService->exchangeCode(request('code'));

use EkstreMedia\LaravelYouTube\Services\TokenManager;

$tokenManager = app(TokenManager::class);

// Store tokens after OAuth
$token = $tokenManager->storeToken(
    $tokens,
    $channelInfo,
    auth()->id()
);

// Get active token for user
$token = $tokenManager->getActiveToken(auth()->id());

// Check if refresh needed (within 5 minutes of expiry)
if ($tokenManager->needsRefresh($token)) {
    $newTokens = $authService->refreshAccessToken($token->refresh_token);
    $tokenManager->updateToken($token, $newTokens);
}

// Handle multiple channels
$tokens = $tokenManager->getUserTokens(auth()->id());
foreach ($tokens as $token) {
    echo "Channel: {$token->channel_title}\n";
}

use EkstreMedia\LaravelYouTube\Facades\YouTube;

// Simple upload
$video = YouTube::forUser(auth()->id())->uploadVideo(
    $request->file('video'),
    [
        'title' => 'My Video',
        'description' => 'Video description',
        'tags' => ['tag1', 'tag2'],
        'category_id' => '22', // People & Blogs
        'privacy_status' => 'private', // private, unlisted, public
    ]
);

// Advanced upload with all metadata options
$video = YouTube::forUser(auth()->id())->uploadVideo(
    '/path/to/large-video.mp4',
    [
        // Basic metadata
        'title' => 'Large Video Upload',
        'description' => 'Testing chunked upload',
        'tags' => ['large', 'chunked'],
        'category_id' => '22',

        // Privacy & Status
        'privacy_status' => 'private',
        'made_for_kids' => false,
        'self_declared_made_for_kids' => false,
        'embeddable' => true,
        'public_stats_viewable' => true,
        'publish_at' => '2024-12-31T12:00:00Z', // Scheduled publishing

        // License & Language
        'license' => 'creativeCommon',
        'default_language' => 'en',
        'default_audio_language' => 'en-US',

        // Recording details (great for travel vlogs, security cameras)
        'recording_date' => '2024-01-15T10:00:00Z',
        'location' => [
            'latitude' => 59.9139,
            'longitude' => 10.7522,
            'altitude' => 100.0,
            'description' => 'Oslo, Norway',
        ],

        // Custom thumbnail
        'thumbnail' => '/path/to/thumbnail.jpg',
    ],
    [
        'chunk_size' => 50 * 1024 * 1024, // 50MB chunks
        'notify_url' => 'https://yourapp.com/webhook',
        'progress_callback' => function ($uploaded, $total) {
            $percent = round(($uploaded / $total) * 100);
            Log::info("Upload progress: {$percent}%");
        }
    ]
);

// Get user's videos
$videos = YouTube::forUser(auth()->id())->getVideos([
    'maxResults' => 50,
    'order' => 'date', // date, rating, relevance, title, viewCount
    'type' => 'video',
    'videoDefinition' => 'high', // any, high, standard
    'videoDuration' => 'medium', // short (<4min), medium (4-20min), long (>20min)
]);

// Get single video details
$video = YouTube::forUser(auth()->id())->getVideo('video-id', [
    'snippet',
    'contentDetails',
    'statistics',
    'status',
    'processingDetails'
]);

// Update video metadata
$updated = YouTube::forUser(auth()->id())->updateVideo('video-id', [
    'title' => 'Updated Title',
    'description' => 'Updated description',
    'tags' => ['new', 'tags'],
    'category_id' => '24',
    'privacy_status' => 'public',
]);

// Delete video
YouTube::forUser(auth()->id())->deleteVideo('video-id');

// Get channel info
$channel = YouTube::forUser(auth()->id())->getChannel([
    'snippet',
    'contentDetails',
    'statistics',
    'brandingSettings',
    'contentOwnerDetails',
    'localizations',
    'status',
    'topicDetails'
]);

// Get channel videos
$videos = YouTube::forUser(auth()->id())->getChannelVideos('channel-id', [
    'maxResults' => 50,
    'order' => 'date',
]);

// Switch between multiple channels
$tokens = YouTubeToken::where('user_id', auth()->id())->get();
foreach ($tokens as $token) {
    $youtube = YouTube::withToken($token);
    $channel = $youtube->getChannel();
    echo "Channel: {$channel['title']} ({$channel['subscriberCount']} subscribers)\n";
}

// Create a new playlist
$playlist = YouTube::usingDefault()->createPlaylist('My Playlist', [
    'description' => 'Collection of my favorite videos',
    'privacy_status' => 'public', // private, public, unlisted
    'tags' => ['favorites', 'collection'],
]);

// Get all playlists
$result = YouTube::usingDefault()->getPlaylists();
foreach ($result['playlists'] as $playlist) {
    echo "{$playlist['title']} - {$playlist['item_count']} videos\n";
}

// Add video to playlist
YouTube::usingDefault()->addVideoToPlaylist(
    'video-id',
    'playlist-id',
    0 // Position (0 = first)
);

// Get videos in a playlist
$result = YouTube::usingDefault()->getPlaylistVideos('playlist-id');
foreach ($result['videos'] as $video) {
    echo "{$video['title']} (position: {$video['position']})\n";
}

// Update playlist
YouTube::usingDefault()->updatePlaylist('playlist-id', [
    'title' => 'Updated Title',
    'privacy_status' => 'public',
]);

// Delete playlist
YouTube::usingDefault()->deletePlaylist('playlist-id');

// Upload captions (supports SRT, VTT, TTML, SBV)
$caption = YouTube::usingDefault()->uploadCaption(
    'video-id',
    'en', // Language code
    '/path/to/captions.srt',
    [
        'name' => 'English Subtitles',
        'is_draft' => false,
    ]
);

// List all captions for a video
$captions = YouTube::usingDefault()->getCaptions('video-id');
foreach ($captions as $caption) {
    echo "{$caption['name']} ({$caption['language']})\n";
}

// Update caption metadata or file
YouTube::usingDefault()->updateCaption(
    'caption-id',
    ['name' => 'Updated English'],
    '/path/to/new-captions.srt' // Optional: new file
);

// Download captions in different formats
$srt = YouTube::usingDefault()->downloadCaption('caption-id', 'srt');
$vtt = YouTube::usingDefault()->downloadCaption('caption-id', 'vtt');
file_put_contents('captions.srt', $srt);

// Delete captions
YouTube::usingDefault()->deleteCaption('caption-id');

// Create your own job
namespace App\Jobs;

use Ekstremedia\LaravelYouTube\Facades\YouTube;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

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

    public function __construct(
        public string $videoPath,
        public array $metadata
    ) {}

    public function handle(): void
    {
        $video = YouTube::usingDefault()->uploadVideo(
            $this->videoPath,
            $this->metadata
        );

        // Clean up temporary file
        unlink($this->videoPath);
    }
}

// Dispatch the job
UploadYouTubeVideo::dispatch(
    videoPath: '/path/to/video.mp4',
    metadata: [
        'title' => 'Queued Upload',
        'description' => 'Uploaded via queue',
        'tags' => ['queued', 'background'],
        'privacy_status' => 'private',
    ]
)->onQueue('media');

// Create live broadcast
$broadcast = YouTube::forUser(auth()->id())->createLiveBroadcast([
    'title' => 'Live Stream',
    'description' => 'Live streaming event',
    'scheduled_start_time' => now()->addHour(),
    'scheduled_end_time' => now()->addHours(2),
    'privacy_status' => 'public',
]);

// Create live stream
$stream = YouTube::forUser(auth()->id())->createLiveStream([
    'title' => 'Stream',
    'description' => 'Stream description',
    'cdn' => [
        'frameRate' => '30fps',
        'resolution' => '1080p',
        'ingestionType' => 'rtmp',
    ],
]);

// Bind stream to broadcast
YouTube::forUser(auth()->id())->bindBroadcastToStream(
    $broadcast['id'],
    $stream['id']
);

// Get video comments
$comments = YouTube::forUser(auth()->id())->getVideoComments('video-id', [
    'maxResults' => 100,
    'order' => 'time', // time, relevance
    'textFormat' => 'plainText', // plainText, html
]);

// Reply to comment
YouTube::forUser(auth()->id())->replyToComment('comment-id', 'Thank you for watching!');

// Moderate comments
YouTube::forUser(auth()->id())->setCommentModerationStatus('comment-id', 'published'); // heldForReview, published, rejected

// Get video analytics (orUser(auth()->id())->getVideoAnalytics('video-id', [
    'metrics' => 'views,estimatedMinutesWatched,averageViewDuration',
    'dimensions' => 'day',
    'startDate' => now()->subDays(30)->format('Y-m-d'),
    'endDate' => now()->format('Y-m-d'),
]);

return [
    'credentials' => [
        'client_id' => env('YOUTUBE_CLIENT_ID'),
        'client_secret' => env('YOUTUBE_CLIENT_SECRET'),
        'redirect_uri' => env('YOUTUBE_REDIRECT_URI', '/youtube/callback'),
    ],

    'scopes' => [
        'https://www.googleapis.com/auth/youtube',
        'https://www.googleapis.com/auth/youtube.upload',
        'https://www.googleapis.com/auth/youtube.readonly',
        'https://www.googleapis.com/auth/youtube.force-ssl',
        'https://www.googleapis.com/auth/youtubepartner',
        'https://www.googleapis.com/auth/youtubepartner-channel-audit',
    ],

    'admin' => [
        'enabled' => env('YOUTUBE_ADMIN_ENABLED', true),
        'prefix' => env('YOUTUBE_ADMIN_PREFIX', 'youtube-admin'),
        'middleware' => ['web'],
        'auth_middleware' => ['auth'],
    ],

    'routes' => [
        'api' => [
            'enabled' => env('YOUTUBE_API_ENABLED', true),
            'prefix' => env('YOUTUBE_API_PREFIX', 'youtube'),
            'middleware' => ['api'],
            'api_middleware' => ['auth:sanctum', 'throttle:60,1'],
        ],
    ],

    'token' => [
        'driver' => 'database',
        'table' => 'youtube_tokens',
        'cache_key' => 'youtube.token.',
        'cache_ttl' => env('YOUTUBE_TOKEN_CACHE_TTL', 3600),
    ],

    'upload' => [
        'chunk_size' => env('YOUTUBE_UPLOAD_CHUNK_SIZE', 1024 * 1024), // 1MB
        'timeout' => env('YOUTUBE_UPLOAD_TIMEOUT', 3600),
        'max_file_size' => env('YOUTUBE_UPLOAD_MAX_SIZE', 128 * 1024 * 1024 * 1024), // 128GB
        'temp_path' => env('YOUTUBE_UPLOAD_TEMP_PATH', storage_path('app/youtube-uploads')),
    ],

    'defaults' => [
        'privacy_status' => env('YOUTUBE_DEFAULT_PRIVACY', 'private'),
        'category_id' => env('YOUTUBE_DEFAULT_CATEGORY', '22'),
        'language' => env('YOUTUBE_DEFAULT_LANGUAGE', 'en'),
    ],

    'rate_limiting' => [
        'enabled' => env('YOUTUBE_RATE_LIMIT_ENABLED', true),
        'max_requests_per_minute' => env('YOUTUBE_RATE_LIMIT_PER_MINUTE', 60),
        'max_requests_per_hour' => env('YOUTUBE_RATE_LIMIT_PER_HOUR', 3000),
    ],

    'logging' => [
        'enabled' => env('YOUTUBE_LOGGING_ENABLED', true),
        'channel' => env('YOUTUBE_LOGGING_CHANNEL', 'youtube'),
        'level' => env('YOUTUBE_LOGGING_LEVEL', 'info'),
    ],
];

protected function schedule(Schedule $schedule)
{
    // Automatically refresh expiring tokens
    $schedule->command('youtube:refresh-tokens')->hourly();

    // Clean up expired tokens daily
    $schedule->command('youtube:clear-expired-tokens')->daily();

    // Sync video statistics every 6 hours
    $schedule->command('youtube:sync-videos')->everySixHours();
}

use EkstreMedia\LaravelYouTube\Exceptions\{
    YouTubeException,
    YouTubeAuthException,
    UploadException,
    TokenException,
    QuotaExceededException
};

try {
    $video = YouTube::forUser($userId)->uploadVideo($file, $metadata);
} catch (QuotaExceededException $e) {
    // Handle quota exceeded
    Log::error("YouTube quota exceeded: " . $e->getMessage());
    // Retry after reset
} catch (UploadException $e) {
    // Handle upload failure
    Log::error("Upload failed: " . $e->getMessage());
} catch (TokenException $e) {
    // Handle token issues
    return redirect()->route('youtube.auth');
} catch (YouTubeException $e) {
    // Handle general YouTube API errors
    Log::error("YouTube API error: " . $e->getYouTubeError());
}

// Listen for events in EventServiceProvider
protected $listen = [
    \EkstreMedia\LaravelYouTube\Events\VideoUploaded::class => [
        \App\Listeners\ProcessUploadedVideo::class,
    ],
    \EkstreMedia\LaravelYouTube\Events\TokenRefreshed::class => [
        \App\Listeners\LogTokenRefresh::class,
    ],
    \EkstreMedia\LaravelYouTube\Events\UploadFailed::class => [
        \App\Listeners\NotifyUploadFailure::class,
    ],
];
bash
php artisan migrate