Загрузка YouTube из VB.NET с API V3

Любой, кто знаком с V3 YouTube API, подскажет, что я могу делать неправильно:

    Dim Service As YoutubeService = GetYouTubeService()

    Dim SourceVideo As String = "C:\TempMedia\Wildlife.wmv"

    Dim Meta As New Video
    Meta.Snippet = New VideoSnippet
    Meta.Snippet.Title = "Test Wildlife Video"
    Meta.Snippet.Description = "This is a test video only"
    Meta.Snippet.CategoryId = "Animals"
    Meta.Snippet.Tags = New List(Of String)
    Meta.Snippet.Tags.Add("Test")
    Meta.Status = New VideoStatus
    Meta.Status.PrivacyStatus = "unlisted"

    Using fs As New FileStream(SourceVideo, FileMode.Open, FileAccess.Read, FileShare.Inheritable)
        Dim UploadRequest As VideosResource.InsertMediaUpload = Service.Videos.Insert(Meta, "snippet,statistics,status", fs, "application/octet-stream")
        UploadRequest.Upload()
        Dim Uploaded = UploadRequest.ResponseBody
    End Using

Немного подумав, это выдает 500 Internal Server Error в SendChunk.

System.Net.WebException was unhandled   HResult=-2146233079   Message=The remote server returned an error: (500) Internal Server Error.   Source=System   StackTrace:
       at System.Net.HttpWebRequest.GetResponse()
       at Google.Apis.Upload.ResumableUpload`1.SendChunk(Stream stream, Uri uri, Int64 position) in c:\code.google.com\google-api-dotnet-client\default\Tools\BuildRelease\bin\Debug\12-20-2012\default\Src\GoogleApis\Apis\Upload\ResumableUpload.cs:line 452
       at Google.Apis.Upload.ResumableUpload`1.Upload() in c:\code.google.com\google-api-dotnet-client\default\Tools\BuildRelease\bin\Debug\12-20-2012\default\Src\GoogleApis\Apis\Upload\ResumableUpload.cs:line 315
       at QUICTools.Workflow.Social.YouTube.QuicYouTube.TestUpload() in C:\Users\kenny.munro.ZAZA\Documents\Visual Studio 2010\Projects\QUIC_V2.0\QUICTools.Workflow.Social.YouTube\QuicYouTube.vb:line 37
       at QLTest.Form1.SimpleButton1_Click(Object sender, EventArgs e) in C:\Users\kenny.munro.ZAZA\Documents\Visual Studio 2010\Projects\QUIC_V2.0\QLTest\Form1.vb:line 4
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at DevExpress.XtraEditors.BaseButton.OnClick(EventArgs e)
       at DevExpress.XtraEditors.BaseButton.OnKeyUp(KeyEventArgs e)
       at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
       at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
       at System.Windows.Forms.Control.WmKeyChar(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at DevExpress.Utils.Controls.ControlBase.WndProc(Message& m)
       at DevExpress.XtraEditors.BaseControl.WndProc(Message& msg)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at QLTest.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()   InnerException:

Я должен признать, что сейчас я в тупике. У кого-нибудь есть рабочий пример загрузки на YouTube с использованием API dotnet V3 или предложения, в которых это может пойти не так?

ОБНОВЛЕНИЕ

Я провел еще один анализ этого с помощью Fiddler. Во-первых, я установил добавленную строку, чтобы установить chunkSize = 10000. Теперь я вижу, что множество фрагментов загружаются очень хорошо и возвращают 308 кодов ответов. Ошибка возвращается последним частичным фрагментом:

PUT /upload/youtube/v3/videos?uploadType=resumable&alt=json&part=snippet%2Cstatus&upload_id=AEnB2UqVVIYV1YyYk27JhhFj_U2WzbK0_ghq0QIRsO1dB1caaMrazd-wlULFZVxvM_pHDZFJkVmUJbYw4oVicI2rfJujdXy4ZQ HTTP/1.1
Content-Range: bytes 26250000-26255829/26255830
Host: www.googleapis.com
Content-Length: 5830

500 Internal Server Error (application/json)

Не слишком уверен, как это может быть чем-то, что я делаю неправильно, но был бы признателен за некоторый вклад/проверку от кого-то, у кого это работает.

Для полноты, вот начальная команда вставки - опять же, все выглядит хорошо для меня:

POST /upload/youtube/v3/videos?uploadType=resumable&alt=json&part=snippet%2Cstatus HTTP/1.1
X-Upload-Content-Type: video/x-ms-wmv
X-Upload-Content-Length: 26255830
Authorization: Bearer ya29.AHES6ZTQsUz4SI-jOnCO8kL3hg_L...
Content-Type: application/json
Host: www.googleapis.com
Content-Length: 168
Connection: Keep-Alive

{"snippet":{"categoryId":"Entertainment","description":"This is a test video only","tags":["Test"],"title":"Test Wildlife Video"},"status":{"privacyStatus":"unlisted"}}
HTTP/1.1 200 OK
Server: HTTP Upload Server Built on Feb 6 2013 15:53:54 (1360194834)
Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&alt=json&part=snippet%2Cstatus&upload_id=AEnB2UqVVIYV1YyYk27JhhFj_U2WzbK0_ghq0QIRsO1dB1caaMrazd-wlULFZVxvM_pHDZFJkVmUJbYw4oVicI2rfJujdXy4ZQ
Date: Tue, 19 Feb 2013 13:58:18 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 0
Content-Type: text/html; charset=UTF-8

person Kenny Munro    schedule 18.02.2013    source источник
comment
Неужели никто не может дать отзыв по этому поводу? Это работает для кого-то еще или это ошибка, которую мне нужно поднять с помощью Google?   -  person Kenny Munro    schedule 04.03.2013
comment
Не могли бы вы опубликовать свой метод GetYouTubeService()?   -  person Pomster    schedule 01.10.2014


Ответы (2)


CategoryId — это число. Вы можете использовать этот пример для загрузки списка идентификаторов (номеров) и заголовков всех допустимых категорий. В этом примере идентификатор и заголовок помещаются в настраиваемый объект класса, а каждый объект класса добавляется в качестве элемента в элемент управления ComboBox.

    OAUth2Credential = Nothing
    Try
        GetGredentials.Wait()
        objYouTubeService = New YouTubeService(New BaseClientService.Initializer() With { _
             .HttpClientInitializer = OAUth2Credential, _
             .ApplicationName = Assembly.GetExecutingAssembly().GetName().Name})
    Catch ex As Exception
        MsgBox(ex.Message)
        End
    End Try
    Dim objCategories As VideoCategoryListResponse = Nothing
    Try
        Dim objRequest As VideoCategoriesResource.ListRequest = New VideoCategoriesResource.ListRequest(objYouTubeService, "id,snippet")
        objRequest.Hl = "en_US"
        objRequest.RegionCode = "US"
        objCategories = objRequest.Execute
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
    cmbCategory.DisplayMember = "Title"
    cmbCategory.ValueMember = "Id"
    For Each obj As VideoCategory In objCategories.Items
        cmbCategory.Items.Add(New CategoryClass(obj.Id, obj.Snippet.Title))
        If obj.Snippet.Title.Contains("News") Then
            intDefaultCategoryIndex = cmbCategory.Items.Count - 1
        End If
    Next
    cmbCategory.SelectedIndex = intDefaultCategoryIndex
    ...

Ниже показано, как я заполняю OAuth2Credential.

Private Async Function GetGredentials() As Task
     Try
         '
         ' ClientId and ClientSecret are found in your client_secret_*****.apps.googleusercontent.com.json file downloaded from 
         ' the Google Developers Console ( https://console.developers.google.com). 
         ' This sample shows the ClientID and ClientSecret in the source code. 
         ' Other samples in the sample library show how to read the Client Secrets from the              ' client_secret_*****.apps.googleusercontent.com.json file. 
         '
         OAUth2Credential = Await GoogleWebAuthorizationBroker.AuthorizeAsync( _
             New ClientSecrets With {.ClientId = "Your Client ID goes here ..............................................", _
                                     .ClientSecret = "Your Client Secret goes here."}, _
                                 {YouTubeService.Scope.Youtube}, "user", CancellationToken.None)
         If OAUth2Credential IsNot Nothing Then
             If OAUth2Credential.Token IsNot Nothing Then
                 AddToLog(String.Concat("Token Issued: ", OAUth2Credential.Token.Issued))
             End If
         End If
     Catch ex As Exception
         MsgBox(ex.Message, MsgBoxStyle.Critical, "Google Authorization")
         End
     End Try
 End Function

Вот как выглядит мой пользовательский класс:

Friend Class CategoryClass
Dim m_Id As String
Dim m_Title As String
Sub New(ByVal Id As String, ByVal Title As String)
     m_Id = Id
     m_Title = Title
End Sub
Property ID As String
      Get
         ID = m_Id
     End Get
     Set(value As String)
         m_Id = value
     End Set
End Property
Property Title As String
     Get
         Title = m_Title
     End Get
     Set(value As String)
         m_Title = value
     End Set
End Property
End Class
person Mike Meinz    schedule 20.06.2014
comment
Не могли бы вы показать мне, как вы создаете переменную OAUth2Credential? - person Pomster; 01.10.2014
comment
Извините за задержку с ответом. Я был за границей без ПК. Я изменил свой ответ, включив подпрограмму GetCredentials. Этот код взят из моей примерной программы, найденной в моем совете статья. - person Mike Meinz; 04.10.2014

Поскольку вы загружаете по частям, почему бы вам не зафиксировать события progress и responsereceived, чтобы вы могли получить больше информации о том, что происходит. Вот как это сделать:

UploadRequest.ChunkSize = 10000;
UploadRequest.ProgressChanged += UploadRequest_ProgressChanged;
UploadRequest.ResponseReceived += UploadRequest_ResponseReceived;

Sub UploadRequest_ProgressChanged(obj As Google.Apis.Upload.IUploadProgress)
    ' check if the upload has been completed            
    If obj.Status = Google.Apis.Upload.UploadStatus.Completed Then
        ' do something here
    End If

    ' or check the status and handle it appropriately
    ' see "Google.Apis.Upload.UploadStatus" for possible status returned


    ' or check the details of the exception here
    If obj.Exception IsNot Nothing Then
        Console.WriteLine(obj.Exception.Message)
    End If
End Sub

Sub UploadRequest_ResponseReceived(Google.Apis.Youtube.v3.Data.Video obj)
    ' your video object will be available here once the upload is done

End Sub

ПРИМЕЧАНИЕ. Я написал это на C# и использовал сайт для конвертации в VB, так что может быть какая-то синтаксическая ошибка, я уверен, что вы знаете, как ее исправить.

person von v.    schedule 07.03.2013