Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload Video to youtube using Google.Apis.YouTube.v3 and C#?

I have created console application using C#. Which will upload Video from local drive to youtube. I have created new app in google api using this link. I have also installed all required packages using nuget. When I run my application I am getting error as "Access Denied" I am not able to find the issue.

I am getting error in Task Run() method.

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;

namespace Google.Apis.YouTube.Samples
{
  /// <summary>
  /// YouTube Data API v3 sample: create a playlist.
  /// Relies on the Google APIs Client Library for .NET, v1.7.0 or higher.
  /// See https://developers.google.com/api-client-library/dotnet/get_started
  /// </summary>
  internal class PlaylistUpdates
  {
    [STAThread]
    static void Main(string[] args)
    {
      Console.WriteLine("YouTube Data API: Playlist Updates");
      Console.WriteLine("==================================");

      try
      {
        new PlaylistUpdates().Run().Wait();
      }
      catch (AggregateException ex)
      {
        foreach (var e in ex.InnerExceptions)
        {
          Console.WriteLine("Error: " + e.Message);
        }
      }

      Console.WriteLine("Press any key to continue...");
      Console.ReadKey();
    }

    private async Task Run()
    {
      UserCredential credential;
      using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
      {
        credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.Load(stream).Secrets,
            // This OAuth 2.0 access scope allows for full read/write access to the
            // authenticated user's account.
            new[] { YouTubeService.Scope.Youtube },
            "user",
            CancellationToken.None,
            new FileDataStore(this.GetType().ToString())
        );
      }

      var youtubeService = new YouTubeService(new BaseClientService.Initializer()
      {
        HttpClientInitializer = credential,
        ApplicationName = this.GetType().ToString()
      });

      // Create a new, private playlist in the authorized user's channel.
      var newPlaylist = new Playlist();
      newPlaylist.Snippet = new PlaylistSnippet();
      newPlaylist.Snippet.Title = "Test Playlist";
      newPlaylist.Snippet.Description = "A playlist created with the YouTube API v3";
      newPlaylist.Status = new PlaylistStatus();
      newPlaylist.Status.PrivacyStatus = "public";
      newPlaylist = await youtubeService.Playlists.Insert(newPlaylist, "snippet,status").ExecuteAsync();

      // Add a video to the newly created playlist.
      var newPlaylistItem = new PlaylistItem();
      newPlaylistItem.Snippet = new PlaylistItemSnippet();
      newPlaylistItem.Snippet.PlaylistId = newPlaylist.Id;
      newPlaylistItem.Snippet.ResourceId = new ResourceId();
      newPlaylistItem.Snippet.ResourceId.Kind = "youtube#video";
      newPlaylistItem.Snippet.ResourceId.VideoId = "GNRMeaz6QRI";
      newPlaylistItem = await youtubeService.PlaylistItems.Insert(newPlaylistItem, "snippet").ExecuteAsync();

      Console.WriteLine("Playlist item id {0} was added to playlist id {1}.", newPlaylistItem.Id, newPlaylist.Id);
    }
  }
}

Do I need to pass 'user' parameter the gmail username?

Any working example using C# (console/web) ?

Help Appreciated.

like image 654
SHEKHAR SHETE Avatar asked Jun 16 '17 16:06

SHEKHAR SHETE


People also ask

How do I enable YouTube API v3?

In Google API dashboard, click Library on the left menu. Click YouTube Data API v3, then click the Enable button to enable the API service.

Is YouTube Data API v3 free?

Yes, using the YouTube API does not incur any monetary cost for the entity calling the API. If you go over your quota an 403 Error will be returned by the API.


1 Answers

All Credit to @iedoc for his code and answer here

A basic working Web project example

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>testing</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <p><asp:TextBox runat="server" ID="videoName" placeholder="Video Title" /></p>
        <p><asp:TextBox runat="server" ID="videoDesc" placeholder="Video Description" /></p>
        <p><asp:FileUpload ID="videoUpload" runat="server" /></p>
        <p><asp:Button id="saveDetails" Text="Update Chapel Group" runat="server" OnClick="saveDetails_click" /></p>
    </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Responses;

public partial class _Default : System.Web.UI.Page
{
    string vID = "none";
    public void Page_Load(object sender, EventArgs e)
    {

    }
    protected void saveDetails_click(object sender, EventArgs e)
    {
        if (Path.GetFileName(videoUpload.PostedFile.FileName) != "")
        {
            YouTubeUtilities ytU = new YouTubeUtilities("REFRESH", "SECRET", "CLIENT_ID"); // pass in your API codes here

            using (var fileStream = videoUpload.PostedFile.InputStream) // the selected post file
            {
                vID = ytU.UploadVideo(fileStream,videoName.Text,videoDesc.Text,"22",false);
            }
            Response.Write(vID);
        }

    }
}
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 categoryId, Boolean isPublic)
    {
        var video = new Video();
        video.Snippet = new VideoSnippet();
        video.Snippet.Title = title;
        video.Snippet.Description = desc;
        video.Snippet.CategoryId = categoryId; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
        video.Status = new VideoStatus();
        video.Status.PrivacyStatus = isPublic ? "public" : "unlisted"; // "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;
    }

    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 hate .NET and I have been fighting with this for weeks. Some of the problems I encountered;

  1. a faulty pair of API Keys, they just didn't work. I guess it was a random bug.
  2. I also have a couple MP4's that I downloaded from Youtube that would not upload back, within creator studio they would say "Upload failed: Can't process file" I determined this by attempting to upload them in the youTube interface. (not through API)
  3. async vs. synchronous was causing me many issues I just don't understand.

I would like to improve this code to provide actual upload status/feedback but I think that would need to be done client side. I am not very good at C#/.NET

UPDATE here is my feedback code via server & client side - https://stackoverflow.com/a/49516167/3790921

like image 83
Chad Avatar answered Oct 01 '22 02:10

Chad