无法成功 运行 包含将视频上传到 YouTube 的代码的 Azure 函数

Not able to successfully run an Azure Function which contains code to Upload Video to YouTube

我基本上是在创建一个 HTTP 触发器 Azure 函数,它具有使用 YouTube API 将视频上传到 YouTube 的代码。代码几乎由 YouTubeAPI 文档提供:https://developers.google.com/youtube/v3/docs/videos/insert。我稍微重新格式化了代码以使其适合 Azure 函数。

但是,当我尝试在 Visual Studio 上本地 运行 函数时,我收到 500 错误消息:

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'.

我不确定如何修复此错误并使函数 运行 没有任何错误。在代码(下面)中是否需要 added/changed 才能解决此问题?

我的目标:我的最终目标是每当有新视频添加到 Azure Blob 存储中时触发此 azure 函数。

代码

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Upload;
using Google.Apis.YouTube.v3.Data;
using System.Reflection;
using Google.Apis.YouTube.v3;
using Google.Apis.Services;
using System.Threading;

namespace UploadVideo
{
    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 = @"C:\Users\Peter\Desktop\audio\test.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);
        }
    }
}

Could not find file 'C:\Users\Peter\Desktop\TestDemo\UploadVideo\UploadVideo\bin\Debug\netcoreapp2.1\client_secrets.json'.

它正在寻找 "client_secrets.json" 它需要与您的代码位于同一目录中。因为你还没有告诉它看其他地方

using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
        {

备注

GoogleWebAuthorizationBroker.AuthorizeAsync 仅设计用于已安装的应用程序,它将打开服务器上的 Web 浏览器并提示用户验证代码。

如果我错了请纠正我,但 azure 函数没有 ui 端点,您可以在其中提示用户进行身份验证。这意味着您唯一可以使用的是服务帐户,而 YouTube api 不支持服务 帐户。

首先,根据您的要求:

My goal: my ultimate goal is to trigger this azure function whenever there is a new video added into the Azure Blob Storage.

您需要使用 Azure blob 触发器来实现您的目标。

从你的错误来看:

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'.

我认为您在创建 json 文件后没有将其属性更改为 'Copy if newer'。如果您不更改此 属性,您将面临此错误。因此它与您的代码在同一文件夹中,但与您的 dll 文件不在同一文件夹中。