YouTube
in package
implements
EventEmitterInterface
uses
EventEmitterTrait, Resources
The YouTube client: the same role `Discord\Discord` plays under DiscordPHP.
It owns the OAuth grant, the Http transport, the Factory, the
quota Meter, and one API object per resource of the Data API v3:
$youtube->liveChatMessages, $youtube->videos, and the rest, generated from
Google's discovery document (Resources).
$youtube = new YouTube([
'client_id' => '...',
'client_secret' => '...',
'token_store' => new EnvFileTokenStore(__DIR__ . '/.env'),
'device_prompt' => fn (array $device) => print("Enter {$device['user_code']} at {$device['verification_uri']}\n"),
]);
$youtube->on('ready', function (YouTube $youtube) {
$youtube->liveBroadcasts->list(part: 'snippet', broadcastStatus: 'active')
->then(fn ($response) => print(count($response->items) . " live now\n"));
});
$youtube->run();
The grant looks after itself:
- Start: a refresh token, from the options or the
token_store, is traded for an access token. With none, adevice_promptsigns in with Google's device flow and the store keeps the result. - Refresh: access tokens last an hour, and each is refreshed five minutes before it runs out. A call that still gets a 401 recovers the token and is retried once.
- Revoked: when Google refuses the refresh token itself (
invalid_grant) the client signs in again. A refresh that fails for any other reason, such as the network, is not a reason to ask anyone for a code.
With only an api_key the client reads public data and signs nobody in.
Events:
| Event | Arguments | When |
|---|---|---|
ready |
YouTube |
Signed in, with the account's channel loaded. |
error |
Throwable, YouTube |
run() could not start. |
token_refreshed |
YouTube |
A new access token from the refresh token. |
reauthorized |
YouTube |
A new grant from signing in again. |
grant_expires |
int seconds, YouTube |
Google will end the grant soon, see below. |
quota.exhausted |
string bucket, CarbonImmutable reset, YouTube |
A quota bucket ran out today. Once a day each. |
closed |
YouTube |
close() was called. |
grant_expires means the Google Cloud project's OAuth consent screen is in
Testing, where every grant ends after seven days. Publishing the app ends
that.
Tags
Table of Contents
Interfaces
- EventEmitterInterface
Constants
- REFRESH_BEFORE : mixed = 300
- Seconds before an access token expires that it is refreshed.
- VERSION : mixed = '1.0.0'
Properties
- $abuseReports : AbuseReportsApi
- Reports of abuse.
- $activities : ActivitiesApi
- What a channel has been doing: uploads, likes, playlist changes and the rest of its feed.
- $captions : CaptionsApi
- The caption tracks of videos.
- $channelBanners : ChannelBannersApi
- Uploading a channel's banner image.
- $channels : ChannelsApi
- Channels, the signed-in account's own included.
- $channelSections : ChannelSectionsApi
- The shelves on a channel's page.
- $comments : CommentsApi
- Single comments and replies, and moderating them.
- $commentThreads : CommentThreadsApi
- Top-level comments, with their replies.
- $i18nLanguages : I18nLanguagesApi
- The interface languages YouTube supports.
- $i18nRegions : I18nRegionsApi
- The content regions YouTube supports.
- $liveBroadcasts : LiveBroadcastsApi
- Live broadcasts: scheduling one, binding it to a stream, going live and ending it.
- $liveChatBans : LiveChatBansApi
- Banning people from a live chat, and lifting bans.
- $liveChatMessages : LiveChatMessagesApi
- Live chat: reading it, posting to it, and deleting from it.
- $liveChatModerators : LiveChatModeratorsApi
- A live chat's moderators.
- $liveStreams : LiveStreamsApi
- The video streams that live broadcasts are fed from.
- $members : MembersApi
- A channel's members, which the API also calls sponsors.
- $membershipsLevels : MembershipsLevelsApi
- A channel's membership levels.
- $playlistImages : PlaylistImagesApi
- Playlists' cover images.
- $playlistItems : PlaylistItemsApi
- The videos in playlists.
- $playlists : PlaylistsApi
- Playlists.
- $search : SearchApi
- Searching for videos, channels and playlists. It has its own quota: 100 calls a day.
- $subscriptions : SubscriptionsApi
- Subscriptions between channels.
- $superChatEvents : SuperChatEventsApi
- The Super Chats and Super Stickers bought on the signed-in channel.
- $tests : TestsApi
- An internal method Google uses to test the API.
- $thirdPartyLinks : ThirdPartyLinksApi
- Links between a channel and third-party services.
- $thumbnails : ThumbnailsApi
- Setting a video's custom thumbnail.
- $videoAbuseReportReasons : VideoAbuseReportReasonsApi
- The reasons a video can be reported for.
- $videoCategories : VideoCategoriesApi
- The categories a video can be filed under.
- $videos : VideosApi
- Videos: listing, uploading, updating, rating and reporting them.
- $videoTrainability : VideoTrainabilityApi
- Whether a video may be used to train AI models.
- $watermarks : WatermarksApi
- A channel's watermark image.
- $channel : ?Channel
- $exhausted : array<string, string>
- $expiresAt : ?int
- When the access token expires, as a Unix time, if known.
- $factory : Factory
- $http : Http
- $loadingChannel : ?PromiseInterface
- $logger : LoggerInterface
- $loop : LoopInterface
- $meter : Meter
- $oauth : OAuth
- $options : array<string, mixed>
- $reauthorizer : ReauthorizerInterface
- $reauthorizing : ?PromiseInterface
- The sign-in in flight, shared the same way.
- $refreshing : ?PromiseInterface
- The refresh in flight, shared by every caller that arrives during it.
- $refreshTimer : ?TimerInterface
- $refreshToken : ?string
- $scopes : array<int, string>
- $token : ?string
- $tokenStore : ?TokenStoreInterface
Methods
- __construct() : mixed
- bootstrap() : PromiseInterface<string|int, Channel|null>
- Signs in, loads the account's channel, and emits `ready`.
- close() : void
- Stops the client's own timers. The loop belongs to whoever runs it, and is left alone.
- getChannel() : ?Channel
- The signed-in account's channel, once {@see me()} has loaded it.
- getFactory() : Factory
- getHttp() : Http
- getLogger() : LoggerInterface
- getLoop() : LoopInterface
- getMeter() : Meter
- Today's quota count.
- getOAuth() : OAuth
- getScopes() : array<int, string>
- isSignedIn() : bool
- Whether calls go out with an access token, rather than an API key or nothing.
- me() : PromiseInterface<string|int, Channel>
- The signed-in account's channel. Loaded once, for one unit of quota.
- reauthorize() : PromiseInterface<string|int, string>
- Gets a brand-new grant from the configured {@see ReauthorizerInterface}.
- refreshAccessToken() : PromiseInterface<string|int, string>
- Trades the refresh token for a fresh access token. Concurrent callers share one attempt. Emits `token_refreshed`.
- request() : PromiseInterface<string|int, mixed>
- Sends one API call, recovering from a dead token once. The generated resource APIs go through here; so can a call to a method this build does not know.
- run() : void
- Bootstraps, then runs the event loop.
- stream() : PromiseInterface<string|int, ResponseInterface>
- Opens a server-streamed call, recovering from a dead token the same way.
- acquireToken() : PromiseInterface<string|int, string|null>
- applyToken() : void
- Adopts a token payload from any grant: hands it to the transport, plans the next refresh, and writes it through to the store.
- bootResources() : void
- Builds every resource API against this client.
- now() : int
- persist() : void
- A store that cannot be written is logged and swallowed: losing it must not fail a call that otherwise worked.
- quotaExhausted() : void
- Tells listeners once a day, per bucket, that its quota is gone.
- recovering() : PromiseInterface
- recoverToken() : PromiseInterface<string|int, string>
- Gets back to a usable token: refresh if there is a refresh token, sign in again if there is not or Google has revoked it.
- resolveOptions() : array<string, mixed>
- scheduleRefresh() : void
- Refreshes the access token a little before it runs out.
Constants
REFRESH_BEFORE
Seconds before an access token expires that it is refreshed.
public
mixed
REFRESH_BEFORE
= 300
VERSION
public
mixed
VERSION
= '1.0.0'
Properties
$abuseReports read-only
Reports of abuse.
public
AbuseReportsApi
$abuseReports
$activities read-only
What a channel has been doing: uploads, likes, playlist changes and the rest of its feed.
public
ActivitiesApi
$activities
$captions read-only
The caption tracks of videos.
public
CaptionsApi
$captions
$channelBanners read-only
Uploading a channel's banner image.
public
ChannelBannersApi
$channelBanners
$channels read-only
Channels, the signed-in account's own included.
public
ChannelsApi
$channels
$channelSections read-only
The shelves on a channel's page.
public
ChannelSectionsApi
$channelSections
$comments read-only
Single comments and replies, and moderating them.
public
CommentsApi
$comments
$commentThreads read-only
Top-level comments, with their replies.
public
CommentThreadsApi
$commentThreads
$i18nLanguages read-only
The interface languages YouTube supports.
public
I18nLanguagesApi
$i18nLanguages
$i18nRegions read-only
The content regions YouTube supports.
public
I18nRegionsApi
$i18nRegions
$liveBroadcasts read-only
Live broadcasts: scheduling one, binding it to a stream, going live and ending it.
public
LiveBroadcastsApi
$liveBroadcasts
$liveChatBans read-only
Banning people from a live chat, and lifting bans.
public
LiveChatBansApi
$liveChatBans
$liveChatMessages read-only
Live chat: reading it, posting to it, and deleting from it.
public
LiveChatMessagesApi
$liveChatMessages
$liveChatModerators read-only
A live chat's moderators.
public
LiveChatModeratorsApi
$liveChatModerators
$liveStreams read-only
The video streams that live broadcasts are fed from.
public
LiveStreamsApi
$liveStreams
$members read-only
A channel's members, which the API also calls sponsors.
public
MembersApi
$members
$membershipsLevels read-only
A channel's membership levels.
public
MembershipsLevelsApi
$membershipsLevels
$playlistImages read-only
Playlists' cover images.
public
PlaylistImagesApi
$playlistImages
$playlistItems read-only
The videos in playlists.
public
PlaylistItemsApi
$playlistItems
$playlists read-only
Playlists.
public
PlaylistsApi
$playlists
$search read-only
Searching for videos, channels and playlists. It has its own quota: 100 calls a day.
public
SearchApi
$search
$subscriptions read-only
Subscriptions between channels.
public
SubscriptionsApi
$subscriptions
$superChatEvents read-only
The Super Chats and Super Stickers bought on the signed-in channel.
public
SuperChatEventsApi
$superChatEvents
$tests read-only
An internal method Google uses to test the API.
public
TestsApi
$tests
$thirdPartyLinks read-only
Links between a channel and third-party services.
public
ThirdPartyLinksApi
$thirdPartyLinks
$thumbnails read-only
Setting a video's custom thumbnail.
public
ThumbnailsApi
$thumbnails
$videoAbuseReportReasons read-only
The reasons a video can be reported for.
public
VideoAbuseReportReasonsApi
$videoAbuseReportReasons
$videoCategories read-only
The categories a video can be filed under.
public
VideoCategoriesApi
$videoCategories
$videos read-only
Videos: listing, uploading, updating, rating and reporting them.
public
VideosApi
$videos
$videoTrainability read-only
Whether a video may be used to train AI models.
public
VideoTrainabilityApi
$videoTrainability
$watermarks read-only
A channel's watermark image.
public
WatermarksApi
$watermarks
$channel
private
?Channel
$channel
= null
$exhausted
private
array<string, string>
$exhausted
= []
Bucket => the quota day it was reported exhausted.
$expiresAt
When the access token expires, as a Unix time, if known.
private
?int
$expiresAt
= null
$factory
private
Factory
$factory
$http
private
Http
$http
$loadingChannel
private
?PromiseInterface
$loadingChannel
= null
$logger
private
LoggerInterface
$logger
$loop
private
LoopInterface
$loop
$meter
private
Meter
$meter
$oauth
private
OAuth
$oauth
$options
private
array<string, mixed>
$options
$reauthorizer
private
ReauthorizerInterface
$reauthorizer
$reauthorizing
The sign-in in flight, shared the same way.
private
?PromiseInterface
$reauthorizing
= null
$refreshing
The refresh in flight, shared by every caller that arrives during it.
private
?PromiseInterface
$refreshing
= null
$refreshTimer
private
?TimerInterface
$refreshTimer
= null
$refreshToken
private
?string
$refreshToken
$scopes
private
array<int, string>
$scopes
= []
The scopes the grant holds, once Google has said.
$token
private
?string
$token
$tokenStore
private
?TokenStoreInterface
$tokenStore
Methods
__construct()
public
__construct([array<string, mixed> $options = [] ]) : mixed
Parameters
- $options : array<string, mixed> = []
-
client_id string The OAuth client's id. client_secret string Its secret. Google needs it even for a device client. token ?string An access token. refresh_token ?string A refresh token, from an earlier sign-in. api_key ?string For public data, when nobody signs in. scopes list
What a sign-in asks for. Default: Scope::YOUTUBE. token_store ?TokenStoreInterface Where the grant is kept between runs. device_prompt ?callable Signs in with the device flow, showing it the code. reauthorize ?ReauthorizerInterface Any other way to sign in again. quota array daily,search,uploads: the project's allowances.reserve: units background work leaves alone.path: a file to keep the count in. loop ?LoopInterface logger ?LoggerInterface socket_options array ForReact\Socket\Connector. driver ?DriverInterface Replaces the HTTP driver, for tests. clock ?\Closure(): float Replaces the clock, for tests.
bootstrap()
Signs in, loads the account's channel, and emits `ready`.
public
bootstrap() : PromiseInterface<string|int, Channel|null>
Return values
PromiseInterface<string|int, Channel|null> —The signed-in account's channel, or null with only an API key.
close()
Stops the client's own timers. The loop belongs to whoever runs it, and is left alone.
public
close() : void
getChannel()
The signed-in account's channel, once {@see me()} has loaded it.
public
getChannel() : ?Channel
Return values
?ChannelgetFactory()
public
getFactory() : Factory
Return values
FactorygetHttp()
public
getHttp() : Http
Return values
HttpgetLogger()
public
getLogger() : LoggerInterface
Return values
LoggerInterfacegetLoop()
public
getLoop() : LoopInterface
Return values
LoopInterfacegetMeter()
Today's quota count.
public
getMeter() : Meter
Return values
MetergetOAuth()
public
getOAuth() : OAuth
Return values
OAuthgetScopes()
public
getScopes() : array<int, string>
Return values
array<int, string> —The scopes the grant holds, once Google has said.
isSignedIn()
Whether calls go out with an access token, rather than an API key or nothing.
public
isSignedIn() : bool
Return values
boolme()
The signed-in account's channel. Loaded once, for one unit of quota.
public
me() : PromiseInterface<string|int, Channel>
Return values
PromiseInterface<string|int, Channel>reauthorize()
Gets a brand-new grant from the configured {@see ReauthorizerInterface}.
public
reauthorize() : PromiseInterface<string|int, string>
Concurrent callers share one attempt, so a burst of 401s cannot ask
anyone for a code twice. Emits reauthorized.
Return values
PromiseInterface<string|int, string> —The new access token.
refreshAccessToken()
Trades the refresh token for a fresh access token. Concurrent callers share one attempt. Emits `token_refreshed`.
public
refreshAccessToken() : PromiseInterface<string|int, string>
Return values
PromiseInterface<string|int, string> —The new access token.
request()
Sends one API call, recovering from a dead token once. The generated resource APIs go through here; so can a call to a method this build does not know.
public
request(string $endpoint, string $method, string $path[, array<string, mixed> $query = [] ][, array<string, mixed>|JsonSerializable|null $body = null ][, ?Media $media = null ][, ?string $uploadPath = null ][, bool $download = false ]) : PromiseInterface<string|int, mixed>
A 401 refreshes the token (or signs in again, if that is what it takes) and the call is retried once. If that fails too, the original 401 is what surfaces: the caller asked about the call, not about the plumbing.
Parameters
- $endpoint : string
- $method : string
- $path : string
- $query : array<string, mixed> = []
- $body : array<string, mixed>|JsonSerializable|null = null
- $media : ?Media = null
- $uploadPath : ?string = null
- $download : bool = false
Return values
PromiseInterface<string|int, mixed> —The decoded JSON, unhydrated.
run()
Bootstraps, then runs the event loop.
public
run() : void
stream()
Opens a server-streamed call, recovering from a dead token the same way.
public
stream(string $endpoint, string $path[, array<string, mixed> $query = [] ]) : PromiseInterface<string|int, ResponseInterface>
Parameters
- $endpoint : string
- $path : string
- $query : array<string, mixed> = []
Return values
PromiseInterface<string|int, ResponseInterface> —See Http::stream().
acquireToken()
private
acquireToken() : PromiseInterface<string|int, string|null>
Return values
PromiseInterface<string|int, string|null> —The access token, or null with only an API key.
applyToken()
Adopts a token payload from any grant: hands it to the transport, plans the next refresh, and writes it through to the store.
private
applyToken(array<string, mixed> $token) : void
Parameters
- $token : array<string, mixed>
bootResources()
Builds every resource API against this client.
private
bootResources() : void
now()
private
now() : int
Return values
intpersist()
A store that cannot be written is logged and swallowed: losing it must not fail a call that otherwise worked.
private
persist(array<string, mixed> $token) : void
Parameters
- $token : array<string, mixed>
quotaExhausted()
Tells listeners once a day, per bucket, that its quota is gone.
private
quotaExhausted(string $endpoint) : void
Parameters
- $endpoint : string
recovering()
private
recovering(string $endpoint, callable(): PromiseInterface $send[, bool $retry = true ]) : PromiseInterface
Parameters
- $endpoint : string
- $send : callable(): PromiseInterface
- $retry : bool = true
Return values
PromiseInterfacerecoverToken()
Gets back to a usable token: refresh if there is a refresh token, sign in again if there is not or Google has revoked it.
private
recoverToken() : PromiseInterface<string|int, string>
Return values
PromiseInterface<string|int, string>resolveOptions()
private
resolveOptions(array<string, mixed> $options) : array<string, mixed>
Parameters
- $options : array<string, mixed>
Return values
array<string, mixed>scheduleRefresh()
Refreshes the access token a little before it runs out.
private
scheduleRefresh() : void