2013-08-22 2 views
1

API-интерфейс YouTube v3 ужасно документирован. Я уже неоднократно сообщал о многочисленных ошибках, но никто не реагирует. Мне еще нужно использовать этот API для загрузки эскизов. Направляющие состояния:Загрузка миниатюр API YouTube v3 с ошибкой

POST https://www.googleapis.com/youtube/v3/thumbnails/set

Auth scopes:

Parameters:

  • videoId: string The videoId parameter specifies a YouTube video ID for which the custom video thumbnail is being provided.

Прежде всего - URL-адрес является неправильным. Это должно быть https://www.googleapis.com/upload/youtube/v3/thumbnails/set. Теперь следующий код, он использует Unirest:

final HttpResponse<String> response = Unirest.post("https://www.googleapis.com/upload/youtube/v3/thumbnails/set") 
        .header("Content-Type", "application/octet-stream") 
        .header("Authorization", accountService.getAuthentication(account).getHeader()) 
        .field("videoId", videoid) 
        .field("thumbnail", thumbnail) 
        .asString(); 

Полученный ответ:

{ 
"error": { 
    "errors": [ 
    { 
    "domain": "global", 
    "reason": "required", 
    "message": "Required parameter: videoId", 
    "locationType": "parameter", 
    "location": "videoId" 
    } 
    ], 
    "code": 400, 
    "message": "Required parameter: videoId" 
} 
} 

Как это может быть? VideoId установлен! Кто-нибудь уже играл с этой частью API?

я могу изменить запрос

Unirest.post("https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId=" + videoid) 
        .header("Content-Type", "application/octet-stream") 
        .header("Authorization", accountService.getAuthentication(account).getHeader()) 
        .field("mediaUpload", thumbnail) 
        .asString(); 

Это отбросит мне эту ошибку:

{ 
"error": { 
    "errors": [ 
    { 
    "domain": "global", 
    "reason": "backendError", 
    "message": "Backend Error" 
    } 
    ], 
    "code": 503, 
    "message": "Backend Error" 
} 
} 

Edit: же запрос с URL, размещенный Ibrahim Ulukaya (исходным URL из справочника):

{ 
"error": { 
    "errors": [ 
    { 
    "domain": "global", 
    "reason": "wrongUrlForUpload", 
    "message": "Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/thumbnails/set" 
    } 
    ], 
    "code": 400, 
    "message": "Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/thumbnails/set" 
} 
} 

ответ

2

Мы выкопали проблему, вот шаги, которые вам необходимо выполнить, если вы не хотите использовать библиотеку.

1) POST https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId=VIDEO_ID&uploadType=resumable с пустым телом

2) получить обратно URL в поле Расположение: заголовок ответа и POST на этот URL с Content-Type: изображения/PNG и миниатюры в корпус

+0

Я хочу использовать библиотеку, но я не могу использовать неполные/неработающие библиотеки: D. Не проверял это, но поверьте, теперь это исправлено. –

+0

Отличный ответ; может ли это быть добавлено в официальную документацию? – spiralman

+0

Конечно, я найду хорошее место, чтобы добавить его. –

1

URL будет исправлен.

Вам также необходимо иметь специальное разрешение на вашем канале для установки пользовательских эскизов.

В нашем примере кода есть PHP и Python.

Вот Java, я только что написал и протестировал, он работает.

/* 
* Copyright (c) 2013 Google Inc. 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 
* in compliance with the License. You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software distributed under the License 
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 
* or implied. See the License for the specific language governing permissions and limitations under 
* the License. 
*/ 

package com.google.api.services.samples.youtube.cmdline.youtube_cmdline_uploadthumbnail_sample; 

import com.google.api.client.auth.oauth2.Credential; 
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; 
import com.google.api.client.extensions.java6.auth.oauth2.FileCredentialStore; 
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; 
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; 
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; 
import com.google.api.client.googleapis.json.GoogleJsonResponseException; 
import com.google.api.client.googleapis.media.MediaHttpUploader; 
import com.google.api.client.googleapis.media.MediaHttpUploaderProgressListener; 
import com.google.api.client.http.HttpTransport; 
import com.google.api.client.http.InputStreamContent; 
import com.google.api.client.http.javanet.NetHttpTransport; 
import com.google.api.client.json.JsonFactory; 
import com.google.api.client.json.jackson2.JacksonFactory; 
import com.google.api.services.youtube.YouTube; 
import com.google.api.services.youtube.YouTube.Thumbnails.Set; 
import com.google.api.services.youtube.model.ThumbnailSetResponse; 
import com.google.common.collect.Lists; 

import java.io.BufferedInputStream; 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.List; 

/** 
* This sample uploads and sets a custom thumbnail for a video by: 
* 
* 1. Uploading a image utilizing "MediaHttpUploader" 2. Setting the uploaded image as a custom 
* thumbnail to the video via "youtube.thumbnails.set" method 
* 
* @author Ibrahim Ulukaya 
*/ 
public class UploadThumbnail { 

    /** 
    * Global instance of the HTTP transport. 
    */ 
    private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 

    /** 
    * Global instance of the JSON factory. 
    */ 
    private static final JsonFactory JSON_FACTORY = new JacksonFactory(); 

    /** 
    * Global instance of Youtube object to make all API requests. 
    */ 
    private static YouTube youtube; 

    /* Global instance of the format used for the image being uploaded (MIME type). */ 
    private static String IMAGE_FILE_FORMAT = "image/png"; 



    /** 
    * Authorizes the installed application to access user's protected data. 
    * 
    * @param scopes list of scopes needed to run youtube upload. 
    */ 
    private static Credential authorize(List<String> scopes) throws IOException { 

    // Load client secrets. 
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, 
     new InputStreamReader(UploadThumbnail.class.getResourceAsStream("/client_secrets.json"))); 

    // Checks that the defaults have been replaced (Default = "Enter X here"). 
    if (clientSecrets.getDetails().getClientId().startsWith("Enter") 
     || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) { 
     System.out.println(
      "Enter Client ID and Secret from https://code.google.com/apis/console/?api=youtube" 
      + "into youtube-cmdline-uploadthumbnail-sample/src/main/resources/client_secrets.json"); 
     System.exit(1); 
    } 

    // Set up file credential store. 
    FileCredentialStore credentialStore = new FileCredentialStore(
     new File(System.getProperty("user.home"), ".credentials/youtube-api-uploadthumbnail.json"), 
     JSON_FACTORY); 

    // Set up authorization code flow. 
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
     HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, scopes).setCredentialStore(credentialStore) 
     .build(); 

    // Build the local server and bind it to port 8080 
    LocalServerReceiver localReceiver = new LocalServerReceiver.Builder().setPort(8080).build(); 

    // Authorize. 
    return new AuthorizationCodeInstalledApp(flow, localReceiver).authorize("user"); 
    } 

    /** 
    * This is a very simple code sample that looks up a user's channel, then features the most 
    * recently uploaded video in the bottom left hand corner of every single video in the channel. 
    * 
    * @param args command line args (not used). 
    */ 
    public static void main(String[] args) { 

    // An OAuth 2 access scope that allows for full read/write access. 
    List<String> scopes = Lists.newArrayList("https://www.googleapis.com/auth/youtube"); 

    try { 
     // Authorization. 
     Credential credential = authorize(scopes); 

     // YouTube object used to make all API requests. 
     youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(
      "youtube-cmdline-addfeaturedvideo-sample").build(); 

     // Get the user selected video Id. 
     String videoId = getVideoIdFromUser(); 
     System.out.println("You chose " + videoId + " to upload a thumbnail."); 

     // Get the user selected local image file to upload. 
     File imageFile = getImageFromUser(); 
     System.out.println("You chose " + imageFile + " to upload."); 

     InputStreamContent mediaContent = new InputStreamContent(
      IMAGE_FILE_FORMAT, new BufferedInputStream(new FileInputStream(imageFile))); 
     mediaContent.setLength(imageFile.length()); 

     // Create a request to set the selected mediaContent as the thumbnail of the selected video. 
     Set thumbnailSet = youtube.thumbnails().set(videoId, mediaContent); 

     // Set the upload type and add event listener. 
     MediaHttpUploader uploader = thumbnailSet.getMediaHttpUploader(); 

     /* 
     * Sets whether direct media upload is enabled or disabled. True = whole media content is 
     * uploaded in a single request. False (default) = resumable media upload protocol to upload 
     * in data chunks. 
     */ 
     uploader.setDirectUploadEnabled(false); 

     MediaHttpUploaderProgressListener progressListener = new MediaHttpUploaderProgressListener() { 
     @Override 
     public void progressChanged(MediaHttpUploader uploader) throws IOException { 
      switch (uploader.getUploadState()) { 
      case INITIATION_STARTED: 
       System.out.println("Initiation Started"); 
       break; 
      case INITIATION_COMPLETE: 
       System.out.println("Initiation Completed"); 
       break; 
      case MEDIA_IN_PROGRESS: 
       System.out.println("Upload in progress"); 
       System.out.println("Upload percentage: " + uploader.getProgress()); 
       break; 
      case MEDIA_COMPLETE: 
       System.out.println("Upload Completed!"); 
       break; 
      case NOT_STARTED: 
       System.out.println("Upload Not Started!"); 
       break; 
      } 
     } 
     }; 
     uploader.setProgressListener(progressListener); 

     // Execute upload and set thumbnail. 
     ThumbnailSetResponse setResponse = thumbnailSet.execute(); 

     // Print out returned results. 
     System.out.println("\n================== Uploaded Thumbnail ==================\n"); 
     System.out.println(" - Url: " + setResponse.getItems().get(0).getDefault().getUrl()); 

    } catch (GoogleJsonResponseException e) { 
     System.err.println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " 
      + e.getDetails().getMessage()); 
     e.printStackTrace(); 

    } catch (IOException e) { 
     System.err.println("IOException: " + e.getMessage()); 
     e.printStackTrace(); 
    } 
    } 

    /* 
    * Prompts for a video ID from standard input and returns it. 
    */ 
    private static String getVideoIdFromUser() throws IOException { 

    String title = ""; 

    System.out.print("Please enter a video Id to update: "); 
    BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in)); 
    title = bReader.readLine(); 

    if (title.length() < 1) { 
     // If nothing is entered, exits 
     System.out.print("Video Id can't be empty!"); 
     System.exit(1); 
    } 

    return title; 
    } 

    /* 
    * Prompts for the path of the image file to upload from standard input and returns it. 
    */ 
    private static File getImageFromUser() throws IOException { 

    String path = ""; 

    System.out.print("Please enter the path of the image file to upload: "); 
    BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in)); 
    path = bReader.readLine(); 

    if (path.length() < 1) { 
     // If nothing is entered, exits 
     System.out.print("Path can not be empty!"); 
     System.exit(1); 
    } 

    return new File(path); 
    } 
} 
+0

Я обновил вопрос. Ответ с исходным URL указан выше. Какие другие разрешения мне нужны? –

+0

Вот почему я ненавижу Google: группа google с отличной поддержкой была закрыта. Мы должны использовать stackoverflow - это потрясающий сайт, но только несколько пользователей имеют опыт работы с youtube-api. Образец Java все еще не подключен. URL, который вы опубликовали и опубликовали по всей документации, недействителен. Отслеживание проблем игнорируется. Ibrahim, мне действительно нужно писать письма по-старому, чтобы получить лучший рабочий API с ошибкой? (Это не только миниатюра, которая нуждается в внимании). Или мне нужно начать работу с @Google? –

+0

добавил мой новый образец –

0

Ответ на этот вопрос не совсем правильный!Если вы размещаете на этот URL без изображения в теле:

https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId=VIDEO_ID&uploadType=resumable

Вы получите эту ошибку:

«400: mediaBodyRequired»

Эта ошибка описана в документации на YouTube в в нижней части этой страницы:

https://developers.google.com/youtube/v3/docs/thumbnails/set

как:

«Запрос не содержит изображения».

Хотя их документация оставляет много вещей (think categoryId), они мертвы здесь, так как я только что попробовал первое решение, отправленное Ibrahim, и получил ошибку. Хотя он заявил, что не предоставляет данные изображения в теле, документация и мои собственные исследования показывают точно противоположное.

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

{ "вид": "YouTube # thumbnailSetResponse", "ETag": "\" kYnGHzMaBhcGeLrcKRx6PAIUosY/lcDPfygjJkG-yyzdBp0dKhY2xMY \ "", "элементы": [{ "по умолчанию": {"url": "//i.ytimg.com/vi/fyBx3v1gmbM/default.jpg", "width": 120, "height": 90}, "medium": {"url": "// i. ytimg.com/vi/fyBx3v1gmbM/mqdefault.jpg "," width ": 320," height ": 180}," high ": {" url ":" //i.ytimg.com/vi/fyBx3v1gmbM/hqdefault. jpg "," width ": 480," height ": 360}," standard ": {" url ":" //i.ytimg.com/vi/fyBx3v1gmbM/sddefault.jpg "," width ": 640," height ": 480}," maxres ": {" url ":" //i.ytimg.com/vi/fyBx3v1gmbM/maxresdefault.jpg "," width ": 1280," height ": 720}}]}

К сожалению, на самом деле это не изменение миниатюры, но я думаю, что это проблема с их API ser ver и очередность их обработки эскизов. Однако он возвращает успешный ответ. Не знаю, почему миниатюра не меняется.

Смежные вопросы