GPAL.YouTube is a fluent YouTube Data API v3 uploader. Build credentials once with CredentialServiceType.Google and the YouTube_Upload scope, set video metadata in a fluent chain, and call Upload to push a video file to your channel. Premiere scheduling is a separate two-phase operation: upload first to collect video IDs, then ScheduleAt polls for processing and sets the premiere time as each video becomes ready.
GPAL.YouTube uses OAuth 2.0 authentication, not a simple API key. You create a project in the Google Cloud Console, enable the YouTube Data API, and obtain a client ID and secret. Build credentials with those values and the YouTube upload scope -- you will need to go through one-time browser consent and save the refresh token so subsequent runs can skip that step. Upload is the terminal call: it streams the file and returns the video ID, a short shareable URL, and the upload status. Privacy can be set to public, private, or unlisted.
ICredentials ytCreds = GPAL.Credentials
.WithService(CredentialServiceType.Google)
.WithServiceKey("your-client-id:your-client-secret")
.WithScope(OAuthScope.YouTube_Upload)
.WithRefreshToken("your-refresh-token")
.ToGPALObject();
YouTubeUploadResult result = GPAL.YouTube
.WithCredentials(ytCreds)
.WithTitle("My First Upload")
.WithPrivacy(YouTubePrivacy.Unlisted)
.Upload((GPALFile)"C:\videos\myvideo.mp4");
Console.WriteLine(result.Url);
Video metadata is set in the fluent chain before Upload: title, description, tags, category, and privacy. The category is chosen from a named enum that maps to YouTube's API category IDs, with Science and Technology as the default. Upload itself just needs a file path -- GPALFile's implicit string conversion means a plain cast is all that's required.
var yt = GPAL.YouTube
.WithCredentials(ytCreds)
.WithCategory(YouTubeCategory.ScienceTechnology)
.WithPrivacy(YouTubePrivacy.Public);
var results = new List<YouTubeUploadResult>();
foreach (var file in videoFiles)
results.Add(yt
.WithTitle(file.Title)
.WithDescription(file.Description)
.WithTags("gpal", "automation", "csharp")
.Upload((GPALFile)file.Path));
Assign the base chain (credentials, category, privacy) to a variable before the loop, then call WithTitle, WithDescription, and Upload inside it. The same GPALYouTube builder is reused each iteration, so shared settings carry forward without being re-specified.
YouTube must finish processing an uploaded video before a premiere time can be set -- uploading and scheduling are two separate API calls. Upload your videos first to collect YouTubeUploadResult objects, then start a new chain with WithVideos. WaitForProcessing sets how often GPAL polls the YouTube API in seconds (default 60). ScheduleAt(PremiereTime) is the terminal call: it fires a non-blocking background thread that polls each video and calls videos.update as each one becomes ready. PremiereTime presets store a relative offset and resolve to now-plus-offset at the moment each video finishes processing, so In30Minutes means thirty minutes after that specific video is ready. WithOutputTo(RichTextBox) pipes scheduling events into a form control. WaitForCompletion blocks the calling thread until all videos are scheduled -- use it in console apps where there is no message loop to keep the process alive.
// Phase 1: upload (synchronous, returns results)
var base = GPAL.YouTube.WithCredentials(ytCreds).WithPrivacy(YouTubePrivacy.Public);
var results = new List<YouTubeUploadResult>();
foreach (var file in videoFiles)
results.Add(base.WithTitle(file.Title).Upload((GPALFile)file.Path));
// Phase 2: schedule premiere (non-blocking background thread)
GPAL.YouTube
.WithCredentials(ytCreds)
.WithVideos(results)
.WaitForProcessing(60)
.WithOutputTo(logRichTextBox)
.ScheduleAt(PremiereTime.In30Minutes);
// form stays open; scheduling events stream into logRichTextBox
// Console apps: block until done
// .ScheduleAt(PremiereTime.In30Minutes).WaitForCompletion();
ScheduleAt fires a background thread and returns right away. In a WinForms app the open form keeps the process alive while polling runs. In a console app the process exits and kills the thread -- call WaitForCompletion() on the return value to block until all videos are scheduled.
Showing off some plain text in these paragraphs eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Here you can find different accents and emphasis sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
This is a link and how it could look like bestlinkinthebeautifulworld. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Here's just some classic bold text adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam notBoldSecondbestlinkinthebeautifulworld illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at adipisicing elit libero vel voluptas? Expedita, adipisicing facere dolores voluptatem ad ab rem assumenda soluta!
Other cuple of colors in case we want to emphasize several ways adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at voluptatem libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repudiandae quas consequuntur illo numquam assumenda autem exercitationem distinctio perspiciatis in natus. Eius dicta similique ipsam ipsa minima, nemo quae enim tempore.
GPAL
.CallIfNotFound(GenericCallIfNotFound)
.WithPublishToConsole();
//System.Drawing.Rectangle windowSize = new System.Drawing.Rectangle(10, 10, 1500, 1024);
// NOTE: we have to set browser = before we execute any steps
// this is due to the 'GenericCallIfNotFound' which might throw an exception, and BankScraper will not have the browser set when it calls scraper.Close()
// until the complete fluent line gets executed (meaning every step, meaning browser is not set until everything else succeeds)
browser = GPAL.Browser
.WithBrowserType(Enums.BrowserType.Chrome)
.WithProfileDataDirectory(ChromeProfileLocation)
.WithUseAutomationEngine(AutomationEngine.Selenium)
.WithWindowSize(new System.Drawing.Rectangle(0,0,1920,1080))
.ToGPALObject();