### Command Line for Metadata JSON Source: https://context7.com/porjo/youtubeuploader/llms.txt Example command to upload a video using a metadata JSON file and output the API response. ```bash ./youtubeuploader -filename tutorial.mp4 -metaJSON video-meta.json -metaJSONout result.json # After upload, result.json contains the full YouTube API response for the video resource ``` -------------------------------- ### Command Line for Rate Limiting Source: https://context7.com/porjo/youtubeuploader/llms.txt Examples of command-line flags for configuring rate limiting, including time windows and constant throttling. ```bash # Throttle to 2000 Kbps only during business hours ./youtubeuploader -filename video.mp4 -ratelimit 2000 -limitBetween 09:00-18:00 # Throttle to 500 Kbps at all times (no window restriction) ./youtubeuploader -filename video.mp4 -ratelimit 500 ``` -------------------------------- ### Metadata Configuration JSON Example Source: https://github.com/porjo/youtubeuploader/blob/master/README.md This JSON structure defines metadata for a YouTube video, including title, description, tags, privacy, and more. Fields specified here take precedence over command-line flags. Use '\n' for newlines in descriptions. ```json { "title": "my test title", "description": "my test description", "tags": [ "test tag1", "test tag2" ], "privacyStatus": "private", "madeForKids": false, "embeddable": true, "license": "creativeCommon", "publicStatsViewable": true, "publishAt": "2017-06-01T12:05:00+02:00", "categoryId": "10", "recordingDate": "2017-05-21", "playlistIds": [ "xxxxxxxxxxxxxxxxxx", "yyyyyyyyyyyyyyyyyy" ], "playlistTitles": [ "my test playlist" ], "language": "fr", "localizations": { "en": { "title": "My English Title", "description": "My English description" }, "it": { "title": "Il mio titolo in italiano", "description": "La mia descrizione in italiano" } }, "containsSyntheticMedia": false } ``` -------------------------------- ### Client Secrets Configuration File Source: https://context7.com/porjo/youtubeuploader/llms.txt The JSON file containing OAuth2 client credentials downloaded from Google Cloud Console. It supports 'web' and 'installed' application types. ```json { "web": { "client_id": "123456789-abcdefg.apps.googleusercontent.com", "project_id": "my-uploader-project", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_secret": "GOCSPX-xxxxxxxxxxxxxxxxxxxx", "redirect_uris": [ "http://localhost:8080/oauth2callback" ] } } ``` -------------------------------- ### Basic Video Upload via Command Line Source: https://context7.com/porjo/youtubeuploader/llms.txt Demonstrates uploading local files, remote URLs, or stdin piped data. Optional flags control title, description, privacy, tags, language, and category. Privacy defaults to 'private' for unverified projects. ```bash # Upload a local file (title defaults to "my-video") ./youtubeuploader -filename my-video.mp4 ``` ```bash # Upload with explicit title and public privacy ./youtubeuploader \ -filename my-video.mp4 \ -title "My Awesome Video" \ -description "A description with\nnewlines supported" \ -privacy public \ -tags "golang,tutorial,demo" \ -language en \ -categoryId 28 ``` ```bash # Upload from a remote URL (streamed through localhost) ./youtubeuploader -filename "https://example.com/video.mp4" -title "Remote Video" ``` ```bash # Upload from stdin (pipe) ffmpeg -i input.mkv -f mp4 - | ./youtubeuploader -filename - -title "Piped Video" ``` ```bash # Expected output: # Uploading file "my-video.mp4" # Progress: 12.34 Mbit/s ( 1.54 MiB/s), 1024k / 10240k (10.0%) ETA 1m, Elapsed 5s # Upload successful! Video ID: dQw4w9WgXcQ ``` -------------------------------- ### Load Video Metadata with Config Struct Source: https://context7.com/porjo/youtubeuploader/llms.txt Merges metadata from a JSON file and CLI flags into a youtube.Video object. JSON file values take precedence over flags. All fields are optional. ```go package main import ( "fmt" "log" yt "github.com/porjo/youtubeuploader" ) func main() { config := yt.Config{ Filename: "my-video.mp4", Title: "My Video Title", // overridden by metaJSON if set Description: "Default description", // supports \n for newlines Language: "en", CategoryId: "28", // Science & Technology Tags: "go,golang,programming", Privacy: "private", // "public", "private", "unlisted" MetaJSON: "video-meta.json", // optional: overrides flag values MetaJSONOut: "uploaded-meta.json", // write API response JSON here PlaylistIDs: []string{"PLxxxxxxxxxxxxxx"}, NotifySubscribers: true, Chunksize: 16 * 1024 * 1024, // 16 MiB chunks (default) SendFileName: true, } videoMeta, video, err := yt.LoadVideoMeta(config) if err != nil { log.Fatalf("error loading metadata: %v", err) } fmt.Printf("Video title: %s\n", video.Snippet.Title) fmt.Printf("Privacy: %s\n", video.Status.PrivacyStatus) fmt.Printf("Playlist IDs: %v\n", videoMeta.PlaylistIDs) // Output: // Video title: My Video Title // Privacy: private // Playlist IDs: [PLxxxxxxxxxxxxxx] } ``` -------------------------------- ### YouTube Uploader CLI Options Source: https://github.com/porjo/youtubeuploader/blob/master/README.md This lists all available command-line options for the youtubeuploader utility. Use these flags to customize your video uploads, including setting titles, descriptions, privacy, and more. ```bash Usage: -cache string token cache file (default "request.token") -caption string caption filename. Can be a URL -categoryId string video category Id -chunksize int size (in bytes) of each upload chunk. A zero value will cause all data to be uploaded in a single request (default 16777216) -debug turn on verbose log output -description string video description (default "uploaded by youtubeuploader") -filename string video filename. Can be a URL. Read from stdin with '-' -language string video language (default "en") -limitBetween string only rate limit between these times e.g. 10:00-14:00 (local time zone) -metaJSON string JSON file containing title,description,tags etc (optional) -metaJSONout string filename to write uploaded video metadata into (optional) -notify notify channel subscribers of new video. Specify '-notify=false' to disable. (default true) -oAuthPort int TCP port to listen on when requesting an oAuth token (default 8080) -playlistID value playlistID to add the video to. Can be used multiple times -privacy string video privacy status (default "private") -quiet suppress progress indicator -ratelimit int rate limit upload in Kbps. No limit by default -recordingDate value recording date e.g. 2024-11-23 -secrets string Client Secrets configuration (default "client_secrets.json") -sendFilename send original file name to YouTube (default true) -tags string comma separated list of video tags -thumbnail string thumbnail filename. Can be a URL -title string video title -version show version ``` -------------------------------- ### Upload Video with Thumbnail and Captions via CLI Source: https://context7.com/porjo/youtubeuploader/llms.txt Uploads a video file, optionally attaching a thumbnail and caption file. The thumbnail and caption can be specified via local paths or URLs. The language for captions can also be set. ```bash # Upload with thumbnail and captions ./youtubeuploader \ -filename my-talk.mp4 \ -title "My Conference Talk" \ -thumbnail https://example.com/thumb.jpg \ -caption subtitles-en.srt \ -language en # Expected output: # Uploading file "my-talk.mp4" # Progress: 8.50 Mbit/s ( 1.06 MiB/s), 512k / 4096k (12.5%) ETA 35s, Elapsed 5s # Upload successful! Video ID: xxxxxxxxxxx # Uploading thumbnail "https://example.com/thumb.jpg"... # Uploading caption "subtitles-en.srt"... ``` -------------------------------- ### Open Video Sources with yt.Open Source: https://context7.com/porjo/youtubeuploader/llms.txt Opens video, image, or caption files from local paths, URLs, or stdin. Performs content-type sniffing and warns on mismatches. Use yt.VIDEO, yt.IMAGE, or yt.CAPTION to specify the expected media type. ```go package main import ( "fmt" "log" yt "github.com/porjo/youtubeuploader" ) func main() { // Local file reader, size, err := yt.Open("video.mp4", yt.VIDEO) if err != nil { log.Fatal(err) } defer reader.Close() fmt.Printf("Local file size: %d bytes\n", size) // Remote URL (HEAD request fetches Content-Length, GET streams body) remoteReader, remoteSize, err := yt.Open("https://example.com/clip.mp4", yt.VIDEO) if err != nil { log.Fatal(err) } defer remoteReader.Close() fmt.Printf("Remote file size: %d bytes\n", remoteSize) // Thumbnail from URL thumbReader, _, err := yt.Open("https://example.com/thumb.jpg", yt.IMAGE) if err != nil { log.Fatal(err) } defer thumbReader.Close() // Caption file captionReader, _, err := yt.Open("subtitles.srt", yt.CAPTION) if err != nil { log.Fatal(err) } defer captionReader.Close() } ``` -------------------------------- ### Basic Video Upload Source: https://github.com/porjo/youtubeuploader/blob/master/README.md To upload a video, at a minimum, specify the filename. The first time you run this, a browser will open for YouTube authentication. Subsequent uploads will use a stored token. ```bash ./youtubeuploader -filename blob.mp4 ``` -------------------------------- ### Full `Run` Function - End-to-End Upload Source: https://context7.com/porjo/youtubeuploader/llms.txt Orchestrates OAuth, rate-limited transport, metadata loading, video/thumbnail/caption upload, and playlist assignment. Configure upload parameters via the `yt.Config` struct. Ensure all necessary files (video, thumbnail, captions) are accessible. ```go package main import ( "context" "log" "net/http" yt "github.com/porjo/youtubeuploader" "github.com/porjo/youtubeuploader/internal/limiter" ) func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() config := yt.Config{ Filename: "presentation.mp4", Title: "Q4 2025 Presentation", Description: "Quarterly results overview.\nSee slides at https://example.com", Language: "en", Privacy: "unlisted", Tags: "quarterly,results,2025", Thumbnail: "thumbnail.png", Caption: "captions.srt", MetaJSONOut: "upload-result.json", PlaylistIDs: []string{"PLxxxxxxxxxxxxxxxxx"}, NotifySubscribers: false, RateLimit: 10000, // 10 Mbit/s cap Chunksize: 16 * 1024 * 1024, OAuthPort: 8080, SendFileName: true, } videoReader, filesize, err := yt.Open(config.Filename, yt.VIDEO) if err != nil { log.Fatal(err) } defer videoReader.Close() transport, err := limiter.NewLimitTransport( http.DefaultTransport, limiter.LimitRange{}, // no time-window restriction filesize, config.RateLimit, ) if err != nil { log.Fatal(err) } if err := yt.Run(ctx, transport, config, videoReader); err != nil { log.Fatalf("upload failed: %v", err) } // Output: // Uploading file "presentation.mp4" // Progress: 10.00 Mbit/s ( 1.25 MiB/s), 12800k / 102400k (12.5%) ETA 1m12s, Elapsed 10s // Upload successful! Video ID: xxxxxxxxxxx // Uploading thumbnail "thumbnail.png"... // Uploading caption "captions.srt"... // Wrote video metadata to file "upload-result.json" // Video added to playlist "My Playlist" (PLxxxxxxxxxxxxxxxxx) } ``` -------------------------------- ### Open Video Sources Source: https://context7.com/porjo/youtubeuploader/llms.txt Opens a video, image, or caption from a local path, HTTP/HTTPS URL, or stdin. Returns a ReadCloser, file size, and error. It performs content-type sniffing and warns if the file doesn't match the expected media type. ```APIDOC ## Open Opens a video, image, or caption from a local path, HTTP/HTTPS URL, or stdin (`-`). Returns a `ReadCloser`, the file size (0 if unknown), and any error. Performs content-type sniffing on local files and warns if the file doesn't match the expected media type. ### Usage ```go reader, size, err := yt.Open(sourcePath, mediaType) ``` ### Parameters - **sourcePath** (string): Local path, HTTP/HTTPS URL, or "-" for stdin. - **mediaType** (yt.MediaType): The expected media type (e.g., `yt.VIDEO`, `yt.IMAGE`, `yt.CAPTION`). ### Returns - **ReadCloser**: An interface for reading the content. - **int64**: The size of the file in bytes (0 if unknown). - **error**: An error if the operation fails. ``` -------------------------------- ### Add Video to Playlists using Go SDK Source: https://context7.com/porjo/youtubeuploader/llms.txt Adds an uploaded video to playlists using the YouTube API. Playlists can be specified by their ID or title; if a title does not exist, it will be created. Requires an authenticated YouTube Service object. ```go package main import ( "fmt" "log" yt "github.com/porjo/youtubeuploader" "google.golang.org/api/youtube/v3" ) func addToPlaylist(service *youtube.Service, videoID string) { // Add by playlist ID plxByID := &yt.Playlistx{ Id: "PLxxxxxxxxxxxxxxxxx", PrivacyStatus: "public", } if err := plxByID.AddVideoToPlaylist(service, videoID); err != nil { log.Fatalf("error adding to playlist by ID: %v", err) } fmt.Printf("Added video %s to playlist by ID\n", videoID) // Add by playlist title (creates the playlist if it doesn't exist) plxByTitle := &yt.Playlistx{ Title: "My Tutorial Series", PrivacyStatus: "public", } if err := plxByTitle.AddVideoToPlaylist(service, videoID); err != nil { log.Fatalf("error adding to playlist by title: %v", err) } fmt.Printf("Added video %s to playlist 'My Tutorial Series'\n", videoID) } ``` -------------------------------- ### Add Video to Playlists via CLI Source: https://context7.com/porjo/youtubeuploader/llms.txt Adds an uploaded video to one or more playlists using the `-playlistID` flag. This flag can be repeated to add the video to multiple playlists simultaneously. ```bash # Add to multiple playlists via CLI (flag can be repeated) ./youtubeuploader \ -filename video.mp4 \ -playlistID PLxxxxxxxxxxxxxxxxx \ -playlistID PLyyyyyyyyyyyyyyyyy ``` -------------------------------- ### Open Function - Open File for Upload Source: https://context7.com/porjo/youtubeuploader/llms.txt The `Open` function is used to open a file for uploading, returning an `io.Reader` and its size. It can be used for video files or thumbnails. ```APIDOC ## Open ### Description Opens a specified file and returns an `io.Reader` along with its size, suitable for uploading. ### Signature `func Open(filename string, filetype FileType) (io.Reader, int64, error)` ### Parameters - **filename** (string) - The path to the file to open. - **filetype** (FileType) - The type of file to open (e.g., `yt.VIDEO`, `yt.THUMBNAIL`). ### Returns - **io.Reader**: An `io.Reader` interface for the file content. - **int64**: The size of the file in bytes. - **error**: An error if the file cannot be opened. ``` -------------------------------- ### Metadata JSON File Structure Source: https://context7.com/porjo/youtubeuploader/llms.txt A JSON file providing full video metadata including scheduled publishing, localizations, and playlist assignment. Values here override any CLI flags. ```json { "title": "My Tutorial Video", "description": "Step 1: ...\nStep 2: ...\nStep 3: ...", "tags": ["golang", "tutorial", "youtube-api"], "privacyStatus": "private", "publishAt": "2025-12-01T09:00:00+00:00", "categoryId": "28", "language": "en", "madeForKids": false, "embeddable": true, "license": "creativeCommon", "publicStatsViewable": true, "recordingDate": "2025-11-15", "containsSyntheticMedia": false, "playlistIds": ["PLxxxxxxxxxxxxxxxxx"], "playlistTitles": ["My Tutorial Series"], "localizations": { "en": { "title": "My Tutorial Video", "description": "English description" }, "es": { "title": "Mi Video Tutorial", "description": "Descripción en español" } } } ``` -------------------------------- ### Run Function - End-to-End Upload Source: https://context7.com/porjo/youtubeuploader/llms.txt The `Run` function is the top-level entry point for programmatic use of the YouTube Uploader. It orchestrates the entire upload process, including OAuth authentication, rate-limited transport, loading metadata, uploading the video, thumbnail, and captions, and assigning the video to playlists. ```APIDOC ## Run ### Description Orchestrates the complete video upload process, including authentication, metadata loading, and file uploads. ### Signature `func Run(ctx context.Context, transport http.RoundTripper, config Config, videoReader io.Reader) error` ### Parameters - **ctx** (context.Context) - The context for the operation. - **transport** (http.RoundTripper) - An HTTP transport, potentially rate-limited. - **config** (Config) - The configuration for the upload, including video details, metadata, and upload settings. - **videoReader** (io.Reader) - An io.Reader for the video file content. ### Request Example ```go package main import ( "context" "log" "net/http" yt "github.com/porjo/youtubeuploader" "github.com/porjo/youtubeuploader/internal/limiter" ) func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() config := yt.Config{ Filename: "presentation.mp4", Title: "Q4 2025 Presentation", Description: "Quarterly results overview.\nSee slides at https://example.com", Language: "en", Privacy: "unlisted", Tags: "quarterly,results,2025", Thumbnail: "thumbnail.png", Caption: "captions.srt", MetaJSONOut: "upload-result.json", PlaylistIDs: []string{"PLxxxxxxxxxxxxxxxxx"}, NotifySubscribers: false, RateLimit: 10000, // 10 Mbit/s cap Chunksize: 16 * 1024 * 1024, OAuthPort: 8080, SendFileName: true, } videoReader, filesize, err := yt.Open(config.Filename, yt.VIDEO) if err != nil { log.Fatal(err) } defer videoReader.Close() transport, err := limiter.NewLimitTransport( http.DefaultTransport, limiter.LimitRange{}, // no time-window restriction filesize, config.RateLimit, ) if err != nil { log.Fatal(err) } if err := yt.Run(ctx, transport, config, videoReader); err != nil { log.Fatalf("upload failed: %v", err) } } ``` ### Response #### Success Response (0) Indicates successful completion of the upload process. The function returns `nil` on success. #### Error Response Returns an error if any part of the upload process fails (e.g., file opening, authentication, upload errors). ``` -------------------------------- ### Rate Limiting Transport with Time Window Source: https://context7.com/porjo/youtubeuploader/llms.txt Wraps the HTTP transport with a token-bucket rate limiter, optionally restricting throttling to a specific daily time window. ```go package main import ( "context" "log" "net/http" yt "github.com/porjo/youtubeuploader" "github.com/porjo/youtubeuploader/internal/limiter" ) func main() { ctx := context.Background() // Parse a time-window for rate limiting: only throttle between 09:00 and 17:00 local time limitRange, err := limiter.ParseLimitBetween("09:00-17:00", "15:04") if err != nil { log.Fatalf("invalid limitBetween: %v", err) } videoReader, filesize, err := yt.Open("large-video.mp4", yt.VIDEO) if err != nil { log.Fatal(err) } defer videoReader.Close() // Create a rate-limited transport: 5000 Kbps = ~5 Mbit/s cap transport, err := limiter.NewLimitTransport( http.DefaultTransport, limitRange, filesize, 5000, // Kbps; set 0 for unlimited ) if err != nil { log.Fatal(err) } _ = transport // passed to yt.Run(ctx, transport, config, videoReader) _ = ctx } ``` -------------------------------- ### Monitor Upload Progress with SIGUSR1 Source: https://context7.com/porjo/youtubeuploader/llms.txt Monitors upload progress in a separate goroutine, displaying speed, transfer stats, and ETA. When the `-quiet` flag is used, progress is suppressed but can be triggered on-demand by sending a SIGUSR1 signal to the process (Linux/Unix only). ```bash # Run upload quietly, then request a one-shot progress report ./youtubeuploader -filename big-video.mp4 -quiet & PID=$! sleep 10 kill -USR1 $PID # prints a single progress line to stdout (Linux/Unix only) wait $PID # Normal (non-quiet) progress output format: # Progress: 25.60 Mbit/s ( 3.20 MiB/s), 16384k / 65536k (25.0%) ETA 30s, Elapsed 10s ``` -------------------------------- ### Playlist Management Source: https://context7.com/porjo/youtubeuploader/llms.txt Adds the uploaded video to one or more playlists. Playlists can be identified by ID or title. If a playlist with the given title does not exist, it will be created. ```APIDOC ## Playlist Management Adds the uploaded video to one or more playlists identified by ID or title. If a playlist with the given title doesn't exist, it is created automatically with the video's privacy status. ### Method ```go func (plx *Playlistx) AddVideoToPlaylist(service *youtube.Service, videoID string) error ``` ### Parameters - **service** (*youtube.Service): The authenticated YouTube API service object. - **videoID** (string): The ID of the video to add to the playlist. ### Playlistx Struct Fields - **Id** (string): The ID of the playlist (used if Title is not provided). - **Title** (string): The title of the playlist (creates playlist if it doesn't exist). - **PrivacyStatus** (string): The privacy status of the playlist ('public', 'private', 'unlisted'). ### Command Line Flags - **-playlistID** (string): The ID of the playlist to add the video to. This flag can be repeated to add to multiple playlists. ### Example ```go // Add by playlist ID plxByID := &yt.Playlistx{ Id: "PLxxxxxxxxxxxxxxxxx", PrivacyStatus: "public", } err := plxByID.AddVideoToPlaylist(service, videoID) // Add by playlist title (creates the playlist if it doesn't exist) plxByTitle := &yt.Playlistx{ Title: "My Tutorial Series", PrivacyStatus: "public", } err := plxByTitle.AddVideoToPlaylist(service, videoID) ``` ```bash # Add to multiple playlists via CLI (flag can be repeated) ./youtubeuploader \ -filename video.mp4 \ -playlistID PLxxxxxxxxxxxxxxxxx \ -playlistID PLyyyyyyyyyyyyyyyyy ``` ``` -------------------------------- ### Thumbnail and Caption Upload Source: https://context7.com/porjo/youtubeuploader/llms.txt Uploads a thumbnail and/or caption file after the video upload is complete. These can be specified via local file paths or URLs using command-line flags. ```APIDOC ## Thumbnail and Caption Upload After the video upload completes, the tool calls `Thumbnails.Set` and `Captions.Insert` on the YouTube API. Both accept local file paths or URLs. ### Command Line Flags - **-thumbnail** (string): Path or URL to the thumbnail image. - **-caption** (string): Path or URL to the caption file. - **-language** (string): The language code for the caption file. ### Example ```bash ./youtubeuploader \ -filename my-talk.mp4 \ -title "My Conference Talk" \ -thumbnail https://example.com/thumb.jpg \ -caption subtitles-en.srt \ -language en ``` ``` -------------------------------- ### Progress Monitoring Source: https://context7.com/porjo/youtubeuploader/llms.txt Monitors and reports upload progress at one-second intervals. Progress can be suppressed with the `-quiet` flag and requested on-demand via SIGUSR1 signal. ```APIDOC ## Progress Monitoring The progress reporter runs in a goroutine, printing upload speed, bytes transferred, percentage, and ETA at one-second intervals. When `-quiet` is set, progress is suppressed but can be requested on-demand by sending `SIGUSR1`. ### Method ```go func (p *Progress) Run() ``` ### Command Line Flags - **-quiet** (bool): Suppresses progress output. If set, progress can be requested manually. ### Signal Handling (Linux/Unix only) - **SIGUSR1**: Sending this signal to the `youtubeuploader` process will trigger a one-time progress report to stdout. ### Progress Output Format ``` Progress: 25.60 Mbit/s ( 3.20 MiB/s), 16384k / 65536k (25.0%) ETA 30s, Elapsed 10s ``` ### Example ```bash # Run upload quietly, then request a one-shot progress report ./youtubeuploader -filename big-video.mp4 -quiet & PID=$! sleep 10 kill -USR1 $PID # prints a single progress line to stdout (Linux/Unix only) wait $PID ``` ``` -------------------------------- ### OAuth2 Authentication with Token Caching Source: https://context7.com/porjo/youtubeuploader/llms.txt Performs the OAuth2 flow, caching tokens for re-use. On first run, it opens a browser for consent; subsequent runs use the cached token. Requires client_secrets.json. ```go package main import ( "context" "fmt" "log" yt "github.com/porjo/youtubeuploader" "google.golang.org/api/youtube/v3" ) func main() { ctx := context.Background() // Reads client_secrets.json from current dir (or OS config dir fallback). // On first run: opens browser for consent, saves token to request.token. // On subsequent runs: loads + refreshes token from request.token automatically. client, err := yt.BuildOAuthHTTPClient( ctx, []string{ youtube.YoutubeUploadScope, // https://www.googleapis.com/auth/youtube.upload youtube.YoutubepartnerScope, // https://www.googleapis.com/auth/youtubepartner youtube.YoutubeScope, // https://www.googleapis.com/auth/youtube }, 8080, // local TCP port for OAuth callback: http://localhost:8080/oauth2callback ) if err != nil { log.Fatalf("OAuth failed: %v", err) } fmt.Println("Authenticated successfully, HTTP client ready:", client) } ``` -------------------------------- ### YouTube API Client Secrets Configuration Source: https://github.com/porjo/youtubeuploader/blob/master/README.md This JSON structure represents the client secrets file required for OAuth2 authentication with the YouTube API. Ensure this file is named `client_secrets.json` and placed in the same directory as the utility. ```json { "web": { "client_id": "xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com", "project_id": "youtubeuploader-yyyyy", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_secret": "xxxxxxxxxxxxxxxxxxxx", "redirect_uris": [ "http://localhost:8080/oauth2callback" ] } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.