javakotlinyoutube-apiyoutube-data-apigoogle-api-java-client

Getting 400 when uploading video with YouTube API


When trying to upload a video using YouTube Data API, I get:

Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
POST https://www.googleapis.com/upload/youtube/v3/videos?part=part&uploadType=resumable
{
  "code": 400,
  "errors": [
    {
      "domain": "youtube.part",
      "location": "part",
      "locationType": "parameter",
      "message": "'part'",
      "reason": "unknownPart"
    }
  ],
  "message": "'part'"
}
    at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
    at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
    at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:432)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
    at YoutubeDataApi.upload(YoutubeDataApi.kt:20)

I'm using the following code to upload:

import com.google.api.client.auth.oauth2.Credential
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp
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.javanet.GoogleNetHttpTransport
import com.google.api.client.http.InputStreamContent
import com.google.api.client.json.gson.GsonFactory
import com.google.api.client.util.store.FileDataStoreFactory
import com.google.api.services.youtube.YouTube
import com.google.api.services.youtube.model.Video
import java.io.*

object YoutubeDataApi {

    fun upload(mediaFile: File) {
        val mediaContent =
            InputStreamContent("application/octet-stream", BufferedInputStream(FileInputStream(mediaFile)))
        mediaContent.length = mediaFile.length()
        service.videos().insert("part", Video(), mediaContent).execute()
    }

    private val gsonFactory = GsonFactory.getDefaultInstance()
    private val httpTransport = GoogleNetHttpTransport.newTrustedTransport()
    private val service = YouTube.Builder(httpTransport, gsonFactory, authorize("userId"))
        .setApplicationName("uploader")
        .build()

    private fun authorize(user: String): Credential? {
        val clientSecretReader: Reader =
            InputStreamReader(this::class.java.getResourceAsStream("/client_secret.json"))
        val clientSecrets = GoogleClientSecrets.load(gsonFactory, clientSecretReader)
        val fileDataStoreFactory = FileDataStoreFactory(File("."))
        val flow = GoogleAuthorizationCodeFlow.Builder(
            httpTransport, gsonFactory, clientSecrets,
            setOf("https://www.googleapis.com/auth/youtube.upload")
        ).setCredentialDataStore(fileDataStoreFactory.getDataStore("datastore_tokens"))
            .setAccessType("offline")
            .build()

        val localReceiver = LocalServerReceiver.Builder().setPort(8090).setCallbackPath("/callback").build()
        return AuthorizationCodeInstalledApp(flow, localReceiver).authorize(user)
    }
}

The code was inspired on the official docs.


Solution

  • The part paramter is a required paramater for the videos.insert method. However the string "part" is not a valid part.

    enter image description here

    Try something more like:

    YouTube.Videos.Insert videoInsert = youtube.videos().insert(
                    "snippet,statistics,status",
                    videoObjectDefiningMetadata, mediaContent);
            MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();