【问题标题】:How to add captions to youtube video with YoutubeApi v3 in .Net如何在 .Net 中使用 Youtube Api v3 为 youtube 视频添加字幕
【发布时间】:2016-04-07 22:38:04
【问题描述】:

我在为上传到我公司的 youtube 频道的视频添加字幕时遇到问题。我想在 .Net 中使用 Google 的 Youtube Api v3 来实现。我能够成功地将视频上传到频道,但在尝试发送字幕时出现以下错误: “System.Net.Http.HttpRequestException:响应状态码不表示成功:403(禁止)。”

据我所知,我的凭据并未禁止我上传字幕。我可以毫无问题地上传视频。

我使用此处的说明创建了刷新令牌: Youtube API single-user scenario with OAuth (uploading videos)

这是我用来创建 YouTubeService 对象的代码:

    private YouTubeService GetYouTubeService()
    {
        string clientId = "clientId";
        string clientSecret = "clientSecret";
        string refreshToken = "refreshToken";
        try
        {
            ClientSecrets secrets = new ClientSecrets()
            {
                ClientId = clientId,
                ClientSecret = clientSecret
            };

            var token = new TokenResponse { RefreshToken = refreshToken };
            var credentials = new UserCredential(new GoogleAuthorizationCodeFlow(
                new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = secrets,
                    Scopes = new[] { YouTubeService.Scope.Youtube, YouTubeService.Scope.YoutubeUpload, YouTubeService.Scope.YoutubeForceSsl }
                }),
                "user",
                token);

            var service = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credentials,
                ApplicationName = "TestProject"
            });

            service.HttpClient.Timeout = TimeSpan.FromSeconds(360);
            return service;
        }
        catch (Exception ex)
        {
            Log.Error("YouTube.GetYouTubeService() => Could not get youtube service. Ex: " + ex);
            return null;
        }

    }

这是我上传字幕文件的代码:

    private void UploadCaptionFile(String videoId)
    {
        try
        {
            Caption caption = new Caption();
            caption.Snippet = new CaptionSnippet();
            caption.Snippet.Name = videoId + "_Caption";
            caption.Snippet.Language = "en";
            caption.Snippet.VideoId = videoId;
            caption.Snippet.IsDraft = false;

            WebRequest req = WebRequest.Create(_urlCaptionPath);
            using (Stream stream = req.GetResponse().GetResponseStream())
            {
                CaptionsResource.InsertMediaUpload captionInsertRequest = _youtubeService.Captions.Insert(caption, "snippet", stream, "*/*");
                captionInsertRequest.Sync = true;
                captionInsertRequest.ProgressChanged += captionInsertRequest_ProgressChanged;
                captionInsertRequest.ResponseReceived += captionInsertRequest_ResponseReceived;

                IUploadProgress result = captionInsertRequest.Upload();
            }
        }
        catch (Exception ex)
        {
            Log.Error("YouTube.UploadCaptionFile() => Unable to upload caption file. Ex: " + ex);
        }
    }

    void captionInsertRequest_ResponseReceived(Caption obj)
    {
        Log.Info("YouTube.captionInsertRequest_ResponseReceived() => Caption ID " + obj.Id + " was successfully uploaded for this clip.");
        Utility.UpdateClip(_videoClip);
    }

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

            case UploadStatus.Failed:
                Log.Error("YouTube.UploadCaptionFile() => An error prevented the upload from completing. " + obj.Exception);
                break;
        }
    }

过去几天我一直在研究这个问题,但我无法取得任何进展。 YouTubeApi v3 没有太多关于添加字幕的信息。我所能找到的只是 v2 的一些旧信息,这需要一些需要我没有的密钥的 POST 调用。我希望能够使用 API 的内置方法添加字幕。

如果有人有处理此问题的经验,我将非常感谢您提供的任何帮助。

编辑:

这是我将视频发送到 YouTube 的代码。

    public string UploadClipToYouTube()
    {
        try
        {
            var video = new Google.Apis.YouTube.v3.Data.Video();
            video.Snippet = new VideoSnippet();
            video.Snippet.Title = _videoClip.Name;
            video.Snippet.Description = _videoClip.Description;
            video.Snippet.Tags = GenerateTags();
            video.Snippet.DefaultAudioLanguage = "en";
            video.Snippet.DefaultLanguage = "en";
            video.Snippet.CategoryId = "22";
            video.Status = new VideoStatus();
            video.Status.PrivacyStatus = "unlisted";

            WebRequest req = WebRequest.Create(_videoPath);
            using (Stream stream = req.GetResponse().GetResponseStream())
            {
                VideosResource.InsertMediaUpload insertRequest = _youtubeService.Videos.Insert(video, "snippet, status", stream, "video/*");
                insertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
                insertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;

                insertRequest.Upload();
            }
            return UploadedVideoId;
        }
        catch (Exception ex)
        {
            Log.Error("YouTube.UploadClipToYoutube() => Error attempting to authenticate for YouTube. Ex: " + ex);
            return "";
        }
    }

    void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
    {
        switch (progress.Status)
        {
            case UploadStatus.Uploading:
                Log.Info("YouTube.videosInsertRequest_ProgressChanged() => Uploading to Youtube. " + progress.BytesSent + " bytes sent.");
                break;

            case UploadStatus.Failed:
                Log.Error("YouTube.videosInsertRequest_ProgressChanged() => An error prevented the upload from completing. Exception: " + progress.Exception);
                break;
        }
    }

    void videosInsertRequest_ResponseReceived(Google.Apis.YouTube.v3.Data.Video video)
    {
        Log.Info("YouTube.videosInsertRequest_ResponseReceived() => Video was successfully uploaded to YouTube.  The YouTube id is " + video.Id);
        UploadedVideoId = video.Id;
        UploadCaptionFile(video.Id);
    }

【问题讨论】:

  • 几个问题。关于身份验证,您是否使用与上传相同的过程?错误是 403 禁止(这很明显,但我认为也值得一问)您的 Caption 数据是否符合constraints。另外,我看过这个similar post,唯一的区别是他收到的错误,你试过检查他的代码吗? :)
  • 视频上传过程与字幕上传过程几乎相同。我将使用我正在使用的视频上传过程更新我的原始帖子。创建凭据时,我将“YouTubeService.Scope.YoutubeForceSsl”作为范围之一,因此一切都应符合约束。我看过类似的帖子;实际上,其中一位回复者是一位前同事,他在离开之前正在从事这个项目,我接手了。不幸的是,他发布的代码不起作用。
  • @Chelsea 这不是v3。版本 3 使用 GoogleWebAuthorizationBrokerFileDataStore 进行 Oauth... 它还使用 awaitasync 操作来防止锁定应用程序。您是否将新版本与旧版本混合在一起?另外我怀疑您没有为您的请求提供用户名,这可能是由于错误或出于安全原因您已将其忽略...

标签: .net youtube youtube-api youtube-data-api captions


【解决方案1】:

好的,我很快就为你准备了一些东西(老实说大约 15 分钟),我从Java 翻译过来。首先,我注意到您当前的代码有很多东西,但这不是 CodeReview

YouTubeApi v3 没有太多关于添加字幕的信息。我所能找到的只是 v2 的一些旧信息

您对此是正确的,目前 (v3) 并非如此,但希望在不久的将来某个时候。这并没有阻止我们修改 v2 对我们有利,因为 api 非常相似......

代码经过试验和测试

private async Task addVideoCaption(string videoID) //pass your video id here..
        {
            UserCredential credential;
            //you should go out and get a json file that keeps your information... You can get that from the developers console...
            using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new[] { YouTubeService.Scope.YoutubeForceSsl, YouTubeService.Scope.Youtube, YouTubeService.Scope.Youtubepartner },
                    "ACCOUNT NAME HERE",
                    CancellationToken.None,
                    new FileDataStore(this.GetType().ToString())
                );
            }
            //creates the service...
            var youtubeService = new Google.Apis.YouTube.v3.YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = this.GetType().ToString(),
            });

            //create a CaptionSnippet object...
            CaptionSnippet capSnippet = new CaptionSnippet();
            capSnippet.Language = "en";
            capSnippet.Name = videoID + "_Caption";
            capSnippet.VideoId = videoID;
            capSnippet.IsDraft = false;

            //create new caption object
            Caption caption = new Caption();       

            //set the completed snippet to the object now...
            caption.Snippet = capSnippet;

            //here we read our .srt which contains our subtitles/captions...
            using (var fileStream = new FileStream("filepathhere", FileMode.Open))
            {
                //create the request now and insert our params...
                var captionRequest = youtubeService.Captions.Insert(caption, "snippet",fileStream,"application/atom+xml");

                //finally upload the request... and wait.
                await captionRequest.UploadAsync();
            }

        }

如果您不知道外观是什么样子或格式如何,这里是一个示例 .srt 文件。

1
00:00:00,599 --> 00:00:03,160
>> Caption Test zaggler@ StackOverflow

2
00:00:03,160 --> 00:00:05,770
>> If you're reading this it worked!

YouTube Video Proof。这是一个大约 5 秒的短片,只是为了向您展示它的工作原理以及它的外观。并且...不,视频不是我的,拿来进行测试 :)

祝你好运,编程愉快!

【讨论】:

  • 欢迎,很高兴我能帮上忙!
  • 本节:credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, new[] { YouTubeService.Scope.YoutubeForceSsl, YouTubeService.Scope.Youtube, YouTubeService.Scope.Youtubepartner }, "此处的帐户名", CancellationToken.None, new FileDataStore(this.GetType().ToString()) );
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 2017-06-15
  • 2013-11-12
  • 2012-12-09
相关资源
最近更新 更多