Example #1
0
 private void ProgressHandler(IUploadProgress obj, VideosResource.InsertMediaUpload video)
 {
     if (obj.Status == UploadStatus.Failed)
     {
         MessageBox.Show(obj.Exception.Message);
         foreach (var help in obj.Exception.Data.Values)
         {
             MessageBox.Show(help.ToString());
         }
     }
     if (obj.Status == UploadStatus.Uploading)
     {
         Dispatcher.BeginInvoke(
             new Action(() =>
         {
             for (int i = 0; i < UploadQueue.Items.Count; i++)
             {
                 System.Windows.Controls.Border UploadEntry = UploadQueue.Items.GetItemAt(i) as System.Windows.Controls.Border;
                 if (UploadEntry.FindChild <TextBlock>("Stats").Text.Contains(video.Body.Snippet.Title))
                 {
                     UploadEntry.FindChild <ProgressBar>("Progress").Value = obj.BytesSent / filesize;
                     string[] Stats         = UploadEntry.FindChild <TextBlock>("Stats").Text.Split('\n');
                     DateTime StartTime     = DateTime.Parse(Stats[2].Substring(12));
                     TimeSpan ElapsedTime   = DateTime.Now - StartTime;
                     TimeSpan RemainingTime = TimeSpan.FromTicks((long)(ElapsedTime.Ticks * (100 - (obj.BytesSent / filesize) * 100)));
                     UploadEntry.FindChild <TextBlock>("Stats").Text = Stats[0] + "\n" + Math.Round(obj.BytesSent / filesize, 3) + "%\n" + Stats[2] + "\nFinished in:\t" + RemainingTime.ToString(@"dd\.hh\:mm\:ss");
                 }
             }
         })
             );
     }
 }
Example #2
0
        /// <summary>
        /// Execute the upload of one file to YouTube.
        /// </summary>
        private static async Task ExecuteUploadProcess()
        {
            const int      HTTP_CLIENT_TIMEOUT_MINUTES = 2;
            UserCredential OAUth2Credential            = null;
            YouTubeService YouTube      = null;
            bool           OKtoContinue = true;

            try
            {
                OAUth2Credential = await GetCredential();

                if (OAUth2Credential != null && OAUth2Credential.Token != null)
                {
                    Console.WriteLine("Token Issued: {0}", OAUth2Credential.Token.Issued);
                }
                else
                {
                    OKtoContinue = false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Google Authorization: {0}", ex.Message);
                OKtoContinue = false;
            }
            if (OKtoContinue)
            {
                try
                {
                    YouTube = new YouTubeService(new BaseClientService.Initializer
                    {
                        HttpClientInitializer = OAUth2Credential,
                        GZipEnabled           = true,
                        ApplicationName       = Assembly.GetExecutingAssembly().GetName().Name
                    });
                    //
                    // Default Timeout is 1 minute 40 seconds.
                    // The following changes it to 2 minutes.
                    YouTube.HttpClient.Timeout = TimeSpan.FromMinutes(HTTP_CLIENT_TIMEOUT_MINUTES);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(String.Format("YouTubeService error: {0}", ex.Message));
                    OKtoContinue = false;
                }
                if (OKtoContinue)
                {
                    Video VideoResource = CreateVideoResource();
                    using (FileStream VideoFileStream = new FileStream(VIDEOFULLPATHFILENAME, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        VideoInsertRequest = YouTube.Videos.Insert(VideoResource, "snippet,status,recordingDetails", VideoFileStream, "video/*");
                        await PerformUpload();

                        VideoFileStream.Close();
                    }
                }
            }
        }
Example #3
0
        internal YouTubeUploadRequest(string FileName,
                                      YouTubeService YouTubeService,
                                      Video Video)
        {
            _dataStream         = new FileStream(FileName, FileMode.Open);
            _videoInsertRequest = YouTubeService.Videos.Insert(Video, "snippet,status", _dataStream, "video/*");

            _videoInsertRequest.ProgressChanged  += VideosInsertRequest_ProgressChanged;
            _videoInsertRequest.ResponseReceived += VideosInsertRequest_ResponseReceived;
        }
Example #4
0
        public void StatusReset()
        {
            mediaStream.Dispose();
            mediaStream = null;

            Progress        = 0;
            UploadingStatus = UploadingStatus.Queued;

            changedThumbnail = true;

            videoInsertRequest = null;
        }
Example #5
0
        private async void UploadToYouTube(StorageFile file)
        {
            ProgressRing.Visibility = Visibility.Visible;
            ProgressRing.IsActive   = true;

            var clientSecretFile = new Uri("ms-appx:///client_id.json");

            UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                clientSecretFile,
                // This OAuth 2.0 access scope allows an application to upload files to the
                // authenticated user's YouTube channel, but doesn't allow other types of access.
                new[] { YouTubeService.Scope.YoutubeUpload },
                "*****@*****.**",
                CancellationToken.None
                );

            var youtubeService = new YouTubeService(new BaseClientService.Initializer
            {
                HttpClientInitializer = credential,
                ApplicationName       = "Lineage Suncasts"
            });

            var video = new Video
            {
                Snippet = new VideoSnippet
                {
                    Title       = $"{file.Name}",
                    Description = "A test recording made by the Suncasts app.",
                    //                    Tags = new string[] {"tag1", "tag2"},
                    CategoryId = "22"
                },
                Status = new VideoStatus {
                    PrivacyStatus = "unlisted"
                }
            };
            // See https://developers.google.com/youtube/v3/docs/videoCategories/list
            // or "private" or "public"

            Stream fs = (await file.OpenReadAsync()).AsStreamForRead();

            VideosResource.InsertMediaUpload videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fs, "video/*");
            videosInsertRequest.ProgressChanged  += OnVideoInsertProgressChanged;
            videosInsertRequest.ResponseReceived += OnVideosInsertRequestResponseReceived;

            videosInsertRequest.ChunkSize = videosInsertRequest.ChunkSize;
            await videosInsertRequest.UploadAsync();

            ProgressRing.IsActive   = false;
            ProgressRing.Visibility = Visibility.Collapsed;
        }
Example #6
0
        public async Task AddVideoAsync(VideoModel videoModel, IProgress <UploadStatusModel> progress, CancellationToken cancellationToken)
        {
            _logger.LogTrace($"{GetType()} - BEGIN {nameof(AddVideoAsync)}");

            try
            {
                YouTubeService ytService = await _ytServiceProvider.CreateServiceAsync(cancellationToken);

                IEnumerable <VideoCategory> categories = await GetCategoriesAsync(cancellationToken);

                VideoCategory category = categories.FirstOrDefault(c => c.Snippet.Title == videoModel.Metadata.Category);

                Video video = new Video();
                video.HydrateFromVideoModel(videoModel.Metadata);
                video.Snippet.CategoryId = category.Id;

                long videoBytesLength = videoModel.VideoStream.Length;

                VideosResource.InsertMediaUpload req = ytService.Videos.Insert(
                    video,
                    new string[] { "snippet", "status" },
                    videoModel.VideoStream,
                    "application/octet-stream"
                    );

                req.NotifySubscribers = true;

                req.ProgressChanged += ((uProgress) =>
                {
                    UploadStatusModel status = new UploadStatusModel(videoModel.Metadata);
                    status.IsComplete = false;
                    status.IsSuccess = false;
                    status.StatusText = $"{uProgress.Status} ({uProgress.BytesSent} bytes sent)";
                    status.CompletionRate = (uProgress.BytesSent * 100) / videoBytesLength;
                    progress.Report(status);
                    _logger.LogInformation($"Upload of video : {uProgress.BytesSent} bytes sent");
                });

                req.ResponseReceived += ((video) =>
                {
                    _logger.LogInformation($"Upload of video is complete : {video.Id}");
                    UploadStatusModel status = new UploadStatusModel(videoModel.Metadata);
                    status.IsComplete = true;

                    videoModel.Metadata.VideoUrl = BuildVideoUrl(video.Id);

                    if (!string.IsNullOrEmpty(video.ProcessingDetails?.ProcessingFailureReason))
                    {
                        _logger.LogError($"Error while processing video upload : {video.ProcessingDetails.ProcessingFailureReason}");
                        _logger.LogError($"{video.ProcessingDetails.ProcessingIssuesAvailability ?? "No reason"}");

                        progress.Report(status);
                    }
                    else
                    {
                        status.IsSuccess = true;
                        status.CompletionRate = 100;
                        progress.Report(status);
                    }
                });

                IUploadProgress res = await req.UploadAsync(cancellationToken);

                videoModel.VideoStream.Close();
            }
            catch (Exception e)
            {
                _logger.LogError("An error occurred while uploading video", e);
                videoModel.VideoStream.Close();
                throw;
            }
        }
Example #7
0
        internal async Task AddVideo()
        {
            Console.WriteLine("Logging in.");

            UserCredential credential;

            try
            {
                using (FileStream stream = new FileStream(Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + @"\client_secrets.json"), FileMode.Open, FileAccess.Read))
                {
                    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                        GoogleClientSecrets.Load(stream).Secrets,
                        new[] { YouTubeService.Scope.Youtube, YouTubeService.Scope.YoutubeUpload },
                        "user",
                        CancellationToken.None
                        );

                    stream.Close();
                    stream.Dispose();
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("Error: " + e.Message);
                throw new Exception("Error: " + e.Message);
            }

            Console.WriteLine("Login OK.");

            YouTubeService youtubeService = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName       = "Google.Apis.Auth"
            });

            string Parts = "snippet";

            Video video = new Video();

            video.Snippet = new VideoSnippet();

            video.Snippet.Title = Configuration[FSM_ArgParser.Title] as string;

            if (Configuration.ContainsKey(FSM_ArgParser.Description))
            {
                video.Snippet.Description = Configuration[FSM_ArgParser.Description] as string;
            }

            if (Configuration.ContainsKey(FSM_ArgParser.Tags))
            {
                video.Snippet.Tags = Configuration[FSM_ArgParser.Tags] as List <string>;
            }

            video.Snippet.CategoryId = Configuration[FSM_ArgParser.CategoryID] as string;


            if (Configuration.ContainsKey(FSM_ArgParser.PrivacyStatus) ||
                Configuration.ContainsKey(FSM_ArgParser.PublicStatsViewable))
            {
                Parts       += ",status";
                video.Status = new VideoStatus();

                if (Configuration.ContainsKey(FSM_ArgParser.PrivacyStatus))
                {
                    video.Status.PrivacyStatus = Configuration[FSM_ArgParser.PrivacyStatus] as string;
                }

                if (Configuration.ContainsKey(FSM_ArgParser.PublicStatsViewable))
                {
                    video.Status.PublicStatsViewable = (bool)Configuration[FSM_ArgParser.PublicStatsViewable];
                }
            }


            if (Configuration.ContainsKey(FSM_ArgParser.Dimension) ||
                Configuration.ContainsKey(FSM_ArgParser.Definition))
            {
                Parts += ",contentDetails";
                video.ContentDetails = new VideoContentDetails();

                if (Configuration.ContainsKey(FSM_ArgParser.Dimension))
                {
                    video.ContentDetails.Dimension = Configuration[FSM_ArgParser.Dimension] as string;
                }

                if (Configuration.ContainsKey(FSM_ArgParser.Definition))
                {
                    video.ContentDetails.Definition = Configuration[FSM_ArgParser.Definition] as string;
                }
            }


            if (Configuration.ContainsKey(FSM_ArgParser.LocationDescription) ||
                Configuration.ContainsKey(FSM_ArgParser.Location_Latitude) ||
                Configuration.ContainsKey(FSM_ArgParser.Location_Longitude) ||
                Configuration.ContainsKey(FSM_ArgParser.RecordingDate))
            {
                Parts += ",recordingDetails";
                video.RecordingDetails = new VideoRecordingDetails();

                if (Configuration.ContainsKey(FSM_ArgParser.LocationDescription))
                {
                    video.RecordingDetails.LocationDescription = Configuration[FSM_ArgParser.LocationDescription] as string;
                }

                if (Configuration.ContainsKey(FSM_ArgParser.RecordingDate))
                {
                    video.RecordingDetails.RecordingDate = (DateTime)Configuration[FSM_ArgParser.RecordingDate];
                }

                if (Configuration.ContainsKey(FSM_ArgParser.Location_Latitude) ||
                    Configuration.ContainsKey(FSM_ArgParser.Location_Longitude))
                {
                    video.RecordingDetails.Location = new GeoPoint();
                    if (Configuration.ContainsKey(FSM_ArgParser.Location_Latitude))
                    {
                        video.RecordingDetails.Location.Latitude = (double)Configuration[FSM_ArgParser.Location_Latitude];
                    }

                    if (Configuration.ContainsKey(FSM_ArgParser.Location_Longitude))
                    {
                        video.RecordingDetails.Location.Longitude = (double)Configuration[FSM_ArgParser.Location_Longitude];
                    }
                }
            }

            string filePath = Configuration[FSM_ArgParser.File] as string;

            Console.WriteLine("Selected file: {0} ", filePath);
            Console.WriteLine("File size: {0} ", FileSize);

            int Chunksize = (int)((FileSize / 100) / ResumableUpload <Video> .MinimumChunkSize) * ResumableUpload <Video> .MinimumChunkSize;

            if (FileSize < ResumableUpload <Video> .MinimumChunkSize)
            {
                Chunksize = ResumableUpload <Video> .MinimumChunkSize;
            }
            else if (FileSize > (ResumableUpload <Video> .MinimumChunkSize * 4 * 40))
            {
                Chunksize = ResumableUpload <Video> .MinimumChunkSize * 4 * 40;
            }

            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, Chunksize / 8))
            {
                Console.WriteLine("Starting upload.");

                VideosResource.InsertMediaUpload videosInsertRequest = youtubeService.Videos.Insert(video, Parts, fileStream, "video/*");

                videosInsertRequest.ChunkSize = Chunksize;

                videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
                TimeMbps = DateTime.Now;
                DataMbps = 0;

                try
                {
                    videosInsertRequest.Upload();
                }
                catch
                {
                }

                const int max_resumes = 25;
                int       resumes     = 0;
                while ((videosInsertRequest.GetProgress().Status != UploadStatus.Completed) && resumes < max_resumes)
                {
                    resumes++;
                    try
                    {
                        videosInsertRequest.Resume();
                    }
                    catch
                    {
                    }
                }

                VideoID = videosInsertRequest.ResponseBody.Id;

                if (videosInsertRequest.GetProgress().Status != UploadStatus.Completed)
                {
                    Console.Error.Write("Upload failed.");
                    throw new Exception("Upload failed.");
                }

                fileStream.Close();
                fileStream.Dispose();
            }

            if (Configuration.ContainsKey(FSM_ArgParser.DisableComment) || Configuration.ContainsKey(FSM_ArgParser.DisableRating) || Configuration.ContainsKey(FSM_ArgParser.DisableVideoRespond))
            {
                Console.WriteLine(
                    "Warning: DisableComment, DisableRating and DisableVideoRespond are no longer functional due to the decrepation of the YouTube v2 API.\n" +
                    "Google refuses to include these options into the YouTube v3 API.\n" +
                    "Please use the YouTube web UI to manipulate these options."
                    );
            }
        }
Example #8
0
        private async Task Run(string title, string description, string[] tags, PrivacyStatus privacyStatus, IFormFile file)
        {
            UserCredential userCredential;

            GoogleAuthorizationCodeFlow.Initializer initializer = new GoogleAuthorizationCodeFlow.Initializer();
            initializer.ClientSecrets = new ClientSecrets()
            {
                ClientId     = _youtubeClientSecret.client_id,
                ClientSecret = _youtubeClientSecret.client_secret
            };
            initializer.Scopes = new string[1]
            {
                YouTubeService.Scope.YoutubeUpload
            };

            //var token = new TokenResponse { RefreshToken = _youtubeClientSecret.token_uri };
            //userCredential = new UserCredential(new GoogleAuthorizationCodeFlow(
            //    new GoogleAuthorizationCodeFlow.Initializer
            //    {
            //        ClientSecrets = initializer.ClientSecrets
            //    }),
            //    "user",
            //    token);
            string token = await GenerateTokenAsync();

            if (token != "")
            {
                userCredential = new UserCredential(new GoogleAuthorizationCodeFlow(initializer), "me", new TokenResponse()
                {
                    RefreshToken     = token,
                    TokenType        = "Bearer",
                    ExpiresInSeconds = new long?(3599L),
                    AccessToken      = token
                });

                YouTubeService youtubeService = new YouTubeService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = userCredential,
                    ApplicationName       = Assembly.GetExecutingAssembly().GetName().Name
                });
                Video video = new Video()
                {
                    Snippet = new VideoSnippet()
                };
                video.Snippet.Title       = title;
                video.Snippet.Tags        = tags;
                video.Snippet.Description = description;
                video.Snippet.CategoryId  = "";
                video.Status = new VideoStatus {
                    PrivacyStatus = privacyStatus.ToString()
                };

                await Task.Run(() =>
                {
                    VideosResource.InsertMediaUpload insertMediaUpload = youtubeService.Videos.Insert(video, "snippet,status", file.OpenReadStream(), "video/*");
                    insertMediaUpload.ProgressChanged  += videosInsertRequest_ProgressChanged;
                    insertMediaUpload.ResponseReceived += VideosInsertRequest_ResponseReceived;
                    insertMediaUpload.UploadAsync().Wait();
                });
            }
            else
            {
                return;
            }
        }
Example #9
0
        private async Task <string> RunPostAsync(string title, string description, string[] tags, PrivacyStatus privacyStatus, IFormFile file)
        {
            try
            {
                var retryCount = 0;
                GoogleAuthorizationCodeFlow.Initializer initializer = new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets()
                    {
                        ClientId     = _youtubeClientSecret.client_id,
                        ClientSecret = _youtubeClientSecret.client_secret
                    },
                    Scopes = new string[1] {
                        YouTubeService.Scope.YoutubeUpload
                    }
                };

ReGenerateToken:
                if (retryCount > 3)
                {
                    return("");
                }

                var token = await GenerateTokenAsync();

                if (token == "")
                {
                    retryCount += 1;
                    goto ReGenerateToken;
                }

                var userCredential = new UserCredential(new GoogleAuthorizationCodeFlow(initializer), "me", new TokenResponse()
                {
                    RefreshToken     = token,
                    TokenType        = "Bearer",
                    ExpiresInSeconds = new long?(3599L),
                    AccessToken      = token
                });

                YouTubeService youtubeService = new YouTubeService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = userCredential,
                    ApplicationName       = Assembly.GetExecutingAssembly().GetName().Name
                });
                Video video = new Video()
                {
                    Snippet = new VideoSnippet()
                };
                video.Snippet.Title       = title;
                video.Snippet.Tags        = tags;
                video.Snippet.Description = description;
                video.Snippet.CategoryId  = "";
                video.Status = new VideoStatus {
                    PrivacyStatus = privacyStatus.ToString()
                };

                VideosResource.InsertMediaUpload insertMediaUpload = youtubeService.Videos.Insert(video, "snippet,status", file.OpenReadStream(), "video/*");
                // insertMediaUpload.ProgressChanged += PostVideosInsertRequest_ProgressChanged;
                // insertMediaUpload.ResponseReceived += PostVideosInsertRequest_ResponseReceived;
                await insertMediaUpload.UploadAsync();

                return(insertMediaUpload.ResponseBody?.Id);
            }
            catch (Exception e)
            {
                return("");
            }
        }
Example #10
0
        private async Task Run()
        {
            UserCredential credential;
            string         clientSecretsPath = CredentialsManager.GetClientSecretsLocation();

            using (FileStream stream = new FileStream(clientSecretsPath, FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    // This OAuth 2.0 access scope allows an application to upload files to the
                    // authenticated user's YouTube channel, but doesn't allow other types of access.
                    new[] { YouTubeService.Scope.YoutubeUpload },
                    "user",
                    CancellationToken.None
                    );
            }
            YouTubeService youtubeService = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName       = Assembly.GetExecutingAssembly().GetName().Name
            });
            Video video = new Video
            {
                Snippet = new VideoSnippet
                {
                    Title       = "Default Video Title",
                    Description = "Default Video Description",
                    Tags        = new[] { "tag1", "tag2" },
                    CategoryId  = "22"
                }
            };

            // See https://developers.google.com/youtube/v3/docs/videoCategories/list
            video.Status = new VideoStatus
            {
                PrivacyStatus = "unlisted"
            };
            // or "private" or "public"
            string filePath = AssetsManager.GetSampleVideoPath(); // Replace with path to actual movie file.

            using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
            {
                VideosResource.InsertMediaUpload videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
                videosInsertRequest.ProgressChanged  += VideosInsertRequestProgressChanged;
                videosInsertRequest.ResponseReceived += VideosInsertRequestResponseReceived;

                await videosInsertRequest.UploadAsync();
            }

            void VideosInsertRequestProgressChanged(IUploadProgress progress)
            {
                switch (progress.Status)
                {
                case UploadStatus.Uploading:
                    Console.WriteLine("{0} bytes sent.", progress.BytesSent);
                    break;

                case UploadStatus.Failed:
                    Console.WriteLine("An error prevented the upload from completing.\n{0}", progress.Exception);
                    break;
                }
            }

            void VideosInsertRequestResponseReceived(Video videoParam)
            {
                Console.WriteLine("Video id '{0}' was successfully uploaded.", videoParam.Id);
            }
        }
Example #11
0
        public async Task <UploadResult> UploadStart(DataChunkSize dataChunkSize = DataChunkSize.ChunkSize_10MB)
        {
            youtubeSession.TryGetTarget(out YouTubeSession session);

            if (UploadingStatus == UploadingStatus.UploadCanceled)
            {
                UploadingStatus = UploadingStatus.Queued;
                video.Id        = null;
                if (mediaStream != null)
                {
                    mediaStream.Dispose();
                }
                mediaStream        = null;
                Progress           = 0;
                TotalUploaded      = 0;
                TimeRemaining      = new TimeSpan();
                videoInsertRequest = null;
                IsManuallyPaused   = false;
            }

            if (video.Id != null && (
                    UploadingStatus == UploadingStatus.UploadFailed ||
                    UploadingStatus == UploadingStatus.UploadCompleted ||
                    UploadingStatus == UploadingStatus.UpdateFailed ||
                    UploadingStatus == UploadingStatus.UpdateComplete
                    ))
            {
                UploadingStatus = UploadingStatus.UpdateStart;

                await UploadThumbnail(video.Id);

                var videoUpdateRequest = session.YouTubeService.Videos.Update(video, "snippet,status");
                var result             = await videoUpdateRequest.ExecuteAsync();

                if (result != null)
                {
                    UploadingStatus = UploadingStatus.UpdateComplete;
                    PC(nameof(UploadingStatus));
                    Completed?.Invoke(this, EventArgs.Empty);
                    return(UploadResult.Succeed);
                }
                else
                {
                    UploadingStatus = UploadingStatus.UpdateFailed;
                    PC(nameof(UploadingStatus));
                    Failed?.Invoke(this, EventArgs.Empty);
                    return(UploadResult.Succeed);
                }
            }

            if (!(UploadingStatus == UploadingStatus.Queued || UploadingStatus == UploadingStatus.UploadFailed))
            {
                return(UploadResult.AlreadyUploading);
            }

            UploadingStatus = UploadingStatus.PrepareUpload;

            bool virIsNull = videoInsertRequest == null;

            if (virIsNull)
            {
                videoInsertRequest = session.YouTubeService.Videos.Insert(video, "snippet,status", mediaStream, "video/*");
                if (videoInsertRequest == null)
                {
                    UploadingStatus = UploadingStatus.UploadFailed;
                    return(UploadResult.FailedUploadRequest);
                }

                DataChunkSize = dataChunkSize;
                videoInsertRequest.ProgressChanged += (uploadProgress) =>
                {
                    TotalUploaded = uploadProgress.BytesSent;
                    Progress      = uploadProgress.BytesSent / ( double )mediaStream.Length;
                    double percentage = (uploadProgress.BytesSent - lastSentBytes) / ( double )mediaStream.Length;
                    lastSentBytes = uploadProgress.BytesSent;
                    double totalSeconds = (DateTime.Now.TimeOfDay - startTime).TotalSeconds;
                    TimeRemaining = Progress != 0 ? TimeSpan.FromSeconds((totalSeconds / Progress) * (1 - Progress)) : TimeSpan.FromDays(999);

                    switch (uploadProgress.Status)
                    {
                    case UploadStatus.Starting:
                        startTime       = DateTime.Now.TimeOfDay;
                        UploadingStatus = UploadingStatus.UploadStart;
                        Started?.Invoke(this, EventArgs.Empty);
                        break;

                    case UploadStatus.Uploading:
                        UploadingStatus = UploadingStatus.Uploading;
                        Uploading?.Invoke(this, EventArgs.Empty);
                        break;

                    case UploadStatus.Failed:
                        UploadingStatus = UploadingStatus.UploadFailed;
                        Failed?.Invoke(this, EventArgs.Empty);
                        break;

                    case UploadStatus.Completed:
                        UploadingStatus = UploadingStatus.UploadCompleted;
                        Uploading?.Invoke(this, EventArgs.Empty);
                        Completed?.Invoke(this, EventArgs.Empty);
                        mediaStream.Dispose();
                        mediaStream = null;
                        break;
                    }

                    PC(nameof(Progress));
                    PC(nameof(UploadingStatus));
                    PC(nameof(TotalUploaded));
                    PC(nameof(TimeRemaining));
                };
                videoInsertRequest.ResponseReceived += async(video) =>
                {
                    await UploadThumbnail(video.Id);

                    foreach (var playlist in Playlists)
                    {
                        playlist.AddVideo(video.Id);
                    }
                };
            }

            try
            {
                startTime = DateTime.Now.TimeOfDay;
                cancellationTokenSource = new CancellationTokenSource();
                var uploadStatus = virIsNull ?
                                   await videoInsertRequest.UploadAsync(cancellationTokenSource.Token) :
                                   await videoInsertRequest.ResumeAsync(cancellationTokenSource.Token);

                cancellationTokenSource.Dispose();
                video = videoInsertRequest.ResponseBody ?? video;
                if (uploadStatus.Status == UploadStatus.NotStarted)
                {
                    UploadingStatus = UploadingStatus.UploadFailed;
                    return(UploadResult.CannotStartUpload);
                }
            }
            catch
            {
                UploadingStatus = UploadingStatus.UploadFailed;
                return(UploadResult.UploadCanceled);
            }

            return(UploadResult.Succeed);
        }