0

I am trying to convert this console app: (https://developers.google.com/youtube/v3/docs/videos/insert) , the contains the code to upload a video to YouTube using the YouTube API. I am trying to place this code in to a Azure Function and use Azure Blob storage to store my YouTube files.

I started with a simple, Http trigger Azure functions and slowly started to insert more code in the function, but as I am doing, I an coming across various errors. Here is the code, I am trying to insert in my Azure Function:

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: upload a video.
  /// 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 UploadVideo
  {
    [STAThread]
    static void Main(string[] args)
    {
      Console.WriteLine("YouTube Data API: Upload Video");
      Console.WriteLine("==============================");

      try
      {
        new UploadVideo().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 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
        );
      }

      var youtubeService = new YouTubeService(new BaseClientService.Initializer()
      {
        HttpClientInitializer = credential,
        ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
      });

      var video = new Video();
      video.Snippet = new VideoSnippet();
      video.Snippet.Title = "Default Video Title";
      video.Snippet.Description = "Default Video Description";
      video.Snippet.Tags = new string[] { "tag1", "tag2" };
      video.Snippet.CategoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
      video.Status = new VideoStatus();
      video.Status.PrivacyStatus = "unlisted"; // or "private" or "public"
      var filePath = @"REPLACE_ME.mp4"; // Replace with path to actual movie file.

      using (var fileStream = new FileStream(filePath, FileMode.Open))
      {
        var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
        videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
        videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;

        await videosInsertRequest.UploadAsync();
      }
    }

    void videosInsertRequest_ProgressChanged(Google.Apis.Upload.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 videosInsertRequest_ResponseReceived(Video video)
    {
      Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
    }
  }
}
  • 1
    which errors are you getting? – Thiago Custodio Feb 14 '20 at 20:36
  • Too many to name, but few them are: namespace could not be found. Also, googlrwebauthorizationbtoker does not exist etc.... My question is how can I copy that code sample that YouTube provided and paste it in, as a azure function? –  Feb 14 '20 at 20:41
  • @Thiago Custodio, Too many to name, but few them are: namespace could not be found. Also, googlrwebauthorizationbtoker does not exist etc.... My question is how can I copy that code sample that YouTube provided and paste it in, as a azure function? –  Feb 14 '20 at 20:48
  • 1
    just to copy and past it will not work. You need to import the packages: Google.Apis.Auth.OAuth2; Google.Apis.Services; Google.Apis.Upload; Google.Apis.Util.Store; Google.Apis.YouTube.v3; Google.Apis.YouTube.v3.Data; – Thiago Custodio Feb 14 '20 at 21:15
  • @Thiago Custodio, I have tried that as well. Do you mind showing it if possible, how it should be set up? –  Feb 14 '20 at 21:21
  • Install-Package Google.Apis.YouTube.v3 -Version 1.43.0.1834 - more info https://www.nuget.org/packages/Google.Apis.YouTube.v3/ – Thiago Custodio Feb 14 '20 at 21:22
  • @Thiago Custodio But as for as the code goes, do you see anything that needs to be fixed or structured? Is it possible for you to show, how to set up the code within a azure function? –  Feb 14 '20 at 21:42
  • Does this answer your question? [Issue with creating an Azure Function that would call into YouTubeAPI to upload the video to YouTube](https://stackoverflow.com/questions/60220938/issue-with-creating-an-azure-function-that-would-call-into-youtubeapi-to-upload) – Marc Feb 15 '20 at 09:54

1 Answers1

0

Sharing the formatted source code wrapped inside the Azure function, however note that you wont be able to use it as-is since it is trying to access the file from the local path. You can refactor it further and pass accessible file path as input parameter.

Few nuget packages / dependencies you would need to install before you can compile is successfully

enter image description here

public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            log.LogInformation("YouTube Data API: Upload Video");
            log.LogInformation("==============================");

            try
            {
                await Run();
            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    log.LogInformation("Error: " + e.Message);
                }
            }

            return new OkObjectResult($"Video Processed..");

        }

        private static 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 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
                );
            }

            var youtubeService = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
            });

            var video = new Video();
            video.Snippet = new VideoSnippet();
            video.Snippet.Title = "Default Video Title";
            video.Snippet.Description = "Default Video Description";
            video.Snippet.Tags = new string[] { "tag1", "tag2" };
            video.Snippet.CategoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
            video.Status = new VideoStatus();
            video.Status.PrivacyStatus = "unlisted"; // or "private" or "public"
            var filePath = @"REPLACE_ME.mp4"; // Replace with path to actual movie file.

            using (var fileStream = new FileStream(filePath, FileMode.Open))
            {
                var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
                videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
                videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;

                await videosInsertRequest.UploadAsync();
            }
        }

        private static void videosInsertRequest_ProgressChanged(Google.Apis.Upload.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;
            }
        }

        private static void videosInsertRequest_ResponseReceived(Video video)
        {
            Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
        }
    }
Bhushan
  • 580
  • 6
  • 19
  • when I ran the azure function locally on Visual Studio, I keep on getting this error: "Executed 'Function1' (Failed, Id=84400f0c-b6e4-4c78-bf55-30c4527a8b5f) System.Private.CoreLib: Exception while executing function: Function1. System.Private.CoreLib: Could not find file 'C:\Users\Peter\Desktop\TestDemo\UploadVideo\UploadVideo\bin\Debug\netcoreapp2.1\client_secrets.json'." I am not sure how to fix this. –  Feb 18 '20 at 23:28