This is just crazy, i've spent a week now trying to figure this out. Everything i find is either deprecated or will just not work.
So this is what i'm trying to do. We have users upload a video, we store the video until it has been approved. once it is approved, we need to upload it to our youtube channel.
The sample from google: https://developers.google.com/youtube/v3/code_samples/dotnet#retrieve_my_uploads will not get past the GoogleWebAuthorizationBroker.AuthorizeAsync because it just hangs forever.
Another problem with this approach is that we need the id after the video is uploaded, and we need to know if the video was uploaded successfully or not, all in sync. you'll see by looking at the code it is using async methods and to get the id of the video there is a callback.
Does anybody have any idea how to upload a video in the back end of an mvc application synchronously?
Ok, so the first problem i had was the authentication was hanging (getting credentials from GoogleWebAuthorizationBroker.AuthorizeAsync). The way around this was to use GoogleAuthorizationCodeFlow, which is not async, and does not try to save anything in the appdata folder.
I needed to get a refresh token, and to do that i followed: Youtube API single-user scenario with OAuth (uploading videos)
To get a refresh token that can be used many times, you have to go to get a client id and secret for an INSTALLED APPLICATION.
The credentials was the tough part, after that things were just fine. One thing to note though, because i spent a couple hours trying to find out what CategoryId was when uploading a video. I couldn't seem to find any real explanation on where the sample code got "22". I found 22 was the default, and meant "People & Blogs".
Heres my code for anybody that needs it (I also needed to be able to delete youtube videos, so i've added that in here to):
public class YouTubeUtilities
{
/*
Instructions to get refresh token:
* https://stackoverflow.com/questions/5850287/youtube-api-single-user-scenario-with-oauth-uploading-videos/8876027#8876027
*
* When getting client_id and client_secret, use installed application, other (this will make the token a long term token)
*/
private String CLIENT_ID {get;set;}
private String CLIENT_SECRET { get; set; }
private String REFRESH_TOKEN { get; set; }
private String UploadedVideoId { get; set; }
private YouTubeService youtube;
public YouTubeUtilities(String refresh_token, String client_secret, String client_id)
{
CLIENT_ID = client_id;
CLIENT_SECRET = client_secret;
REFRESH_TOKEN = refresh_token;
youtube = BuildService();
}
private YouTubeService BuildService()
{
ClientSecrets secrets = new ClientSecrets()
{
ClientId = CLIENT_ID,
ClientSecret = CLIENT_SECRET
};
var token = new TokenResponse { RefreshToken = REFRESH_TOKEN };
var credentials = new UserCredential(new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = secrets
}),
"user",
token);
var service = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "TestProject"
});
//service.HttpClient.Timeout = TimeSpan.FromSeconds(360); // Choose a timeout to your liking
return service;
}
public String UploadVideo(Stream stream, String title, String desc, String[] tags, String categoryId, Boolean isPublic)
{
var video = new Video();
video.Snippet = new VideoSnippet();
video.Snippet.Title = title;
video.Snippet.Description = desc;
video.Snippet.Tags = tags;
video.Snippet.CategoryId = categoryId; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
video.Status = new VideoStatus();
video.Status.PrivacyStatus = isPublic ? "public" : "private"; // "private" or "public" or unlisted
//var videosInsertRequest = youtube.Videos.Insert(video, "snippet,status", stream, "video/*");
var videosInsertRequest = youtube.Videos.Insert(video, "snippet,status", stream, "video/*");
videosInsertRequest.ProgressChanged += insertRequest_ProgressChanged;
videosInsertRequest.ResponseReceived += insertRequest_ResponseReceived;
videosInsertRequest.Upload();
return UploadedVideoId;
}
public void DeleteVideo(String videoId)
{
var videoDeleteRequest = youtube.Videos.Delete(videoId);
videoDeleteRequest.Execute();
}
void insertRequest_ResponseReceived(Video video)
{
UploadedVideoId = video.Id;
// video.ID gives you the ID of the Youtube video.
// you can access the video from
// http://www.youtube.com/watch?v={video.ID}
}
void insertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
{
// You can handle several status messages here.
switch (progress.Status)
{
case UploadStatus.Failed:
UploadedVideoId = "FAILED";
break;
case UploadStatus.Completed:
break;
default:
break;
}
}
}
I haven't tried it, but from what i understand ApplicatioName can be whatever you want. I was just testing, and this is the project name i have in youtube for the client id and secret, but i think you can just put anything?