Videos: insert

Sube un video a YouTube y configura opcionalmente sus metadatos.

Este método admite la carga de medios. Los archivos cargados deben cumplir con los siguientes requisitos:

  • Tamaño máximo de los archivos: 256 GB.
  • Tipos de MIME de medios aceptados: video/*, application/octet-stream.

Impacto en la cuota: 100 llamadas por día. Una llamada a este método tiene un costo de cuota de 1 unidad en el bucket de cuota de cargas de video.

Casos de uso habituales

Solicitud

Solicitud HTTP

POST https://www.googleapis.com/upload/youtube/v3/videos

Autorización

Esta solicitud requiere autorización con al menos uno de los siguientes alcances (obtén más información acerca de la autenticación y autorización).

Alcance
https://www.googleapis.com/auth/youtube.upload
https://www.googleapis.com/auth/youtube
https://www.googleapis.com/auth/youtubepartner
https://www.googleapis.com/auth/youtube.force-ssl

Parámetros

En la siguiente tabla, se enumeran los parámetros que admite esta consulta. Todos los parámetros mencionados son parámetros de consulta.

Parámetros
Parámetros obligatorios
part string
El parámetro part tiene dos propósitos en esta operación. Identifica las propiedades que establecerá la operación de escritura, así como las propiedades que incluirá la respuesta de la API.

Ten en cuenta que no todas las partes contienen propiedades que se pueden establecer cuando se inserta o actualiza un video. Por ejemplo, el objeto statistics encapsula las estadísticas que YouTube calcula para un video y no contiene valores que puedas establecer o modificar. Si el valor del parámetro especifica una part que no contiene valores mutables, esa part se incluirá en la respuesta de la API.

La siguiente lista contiene los nombres de part que puedes incluir en el valor del parámetro:
  • brandPartner
  • contentDetails
  • fileDetails
  • id
  • liveStreamingDetails
  • localizations
  • paidProductPlacementDetails
  • player
  • processingDetails
  • recordingDetails
  • snippet
  • statistics
  • status
  • suggestions
  • topicDetails
Parámetros opcionales
notifySubscribers boolean
El parámetro notifySubscribers indica si YouTube debe enviar una notificación sobre el video nuevo a los usuarios que se suscriben al canal del video. Un valor de parámetro de True indica que se notificará a los suscriptores sobre los videos recién subidos. Sin embargo, un propietario del canal que sube muchos videos podría preferir establecer el valor en False para evitar enviar una notificación sobre cada video nuevo a los suscriptores del canal. El valor predeterminado es True.
onBehalfOfContentOwner string
Este parámetro solo se puede usar en una solicitud autorizada correctamente. Nota: Este parámetro está destinado exclusivamente a socios de contenido de YouTube.

El parámetro onBehalfOfContentOwner indica que las credenciales de autorización de la solicitud identifican a un usuario de CMS de YouTube que actúa en nombre del propietario del contenido especificado en el valor del parámetro. Este parámetro está dirigido a socios de contenido de YouTube que poseen y administran muchos canales de YouTube diferentes. Permite a los propietarios del contenido autenticarse una vez y tener acceso a todos los datos de sus videos y canales, sin tener que proporcionar credenciales de autenticación para cada canal. La cuenta de CMS con la que se autentica el usuario debe estar relacionada con el propietario del contenido de YouTube especificado.
onBehalfOfContentOwnerChannel string
Este parámetro solo se puede usar en una solicitud autorizada correctamente. Este parámetro solo se puede usar en una solicitud autorizada correctamente. Nota: Este parámetro está destinado exclusivamente a socios de contenido de YouTube.

El parámetro onBehalfOfContentOwnerChannel especifica el ID del canal de YouTube al que se agrega un video. Este parámetro es obligatorio cuando una solicitud especifica un valor para el parámetro onBehalfOfContentOwner y solo se puede usar junto con ese parámetro. Además, la solicitud debe autorizarse con una cuenta de CMS vinculada al propietario del contenido que especifica el parámetro onBehalfOfContentOwner. Por último, el canal que especifica el valor del parámetro onBehalfOfContentOwnerChannel debe estar vinculado al propietario del contenido que especifica el parámetro onBehalfOfContentOwner.

Este parámetro está dirigido a socios de contenido de YouTube que poseen y administran muchos canales de YouTube diferentes. Permite a los propietarios de contenido autenticarse una vez y llevar a cabo acciones en nombre del canal especificado en el valor del parámetro, sin tener que proporcionar credenciales de autenticación para cada canal por separado.

Cuerpo de la solicitud

Proporciona un recurso de video en el cuerpo de la solicitud. Para ese recurso:

  • Puedes establecer los valores de las siguientes propiedades:

    • snippet.title
    • snippet.description
    • snippet.tags[]
    • snippet.categoryId
    • snippet.defaultLanguage
    • localizations.(key)
    • localizations.(key).title
    • localizations.(key).description
    • status.embeddable
    • status.license
    • status.privacyStatus: Si no especificas un valor para esta propiedad, el estado de privacidad del video subido se establece de forma predeterminada en public. Es posible que algunas cargas se establezcan de forma predeterminada en private según la configuración de la cuenta del creador, como se explica en el Centro de ayuda de YouTube. Los videos subidos desde proyectos de API sin verificar no están restringidos al modo de visualización privada.
    • status.publicStatsViewable
    • status.publishAt
    • status.selfDeclaredMadeForKids
    • status.containsSyntheticMedia
    • recordingDetails.recordingDate

Respuesta

Si se aplica correctamente, este método muestra un recurso de video en el cuerpo de la respuesta.

Ejemplos

Nota: Es posible que las siguientes muestras de código no representen todos los lenguajes de programación admitidos. Consulta la documentación de las bibliotecas cliente para obtener una lista de los lenguajes admitidos.

Go

En esta muestra de código, se llama al método videos.insert de la API para subir un video al canal asociado con la solicitud.

En este ejemplo se utiliza la biblioteca cliente Go.

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"google.golang.org/api/youtube/v3"
)

var (
	filename    = flag.String("filename", "", "Name of video file to upload")
	title       = flag.String("title", "Test Title", "Video title")
	description = flag.String("description", "Test Description", "Video description")
	category    = flag.String("category", "22", "Video category")
	keywords    = flag.String("keywords", "", "Comma separated list of video keywords")
	privacy     = flag.String("privacy", "unlisted", "Video privacy status")
)

func main() {
	flag.Parse()

	if *filename == "" {
		log.Fatalf("You must provide a filename of a video file to upload")
	}

	client := getClient(youtube.YoutubeUploadScope)

	service, err := youtube.New(client)
	if err != nil {
		log.Fatalf("Error creating YouTube client: %v", err)
	}

	upload := &youtube.Video{
		Snippet: &youtube.VideoSnippet{
			Title:       *title,
			Description: *description,
			CategoryId:  *category,
		},
		Status: &youtube.VideoStatus{PrivacyStatus: *privacy},
	}

	// The API returns a 400 Bad Request response if tags is an empty string.
	if strings.Trim(*keywords, "") != "" {
		upload.Snippet.Tags = strings.Split(*keywords, ",")
	}

	call := service.Videos.Insert("snippet,status", upload)

	file, err := os.Open(*filename)
	defer file.Close()
	if err != nil {
		log.Fatalf("Error opening %v: %v", *filename, err)
	}

	response, err := call.Media(file).Do()
	handleError(err, "")
	fmt.Printf("Upload successful! Video ID: %v\n", response.Id)
}

.NET

En la siguiente muestra de código, se llama al método videos.insert de la API para subir un video al canal asociado con la solicitud.

En este ejemplo se utiliza la biblioteca cliente.NET.

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;

namespace Google.Apis.YouTube.Samples
{
  /// <summary>
  /// YouTube Data API v3 sample: upload a video.
  /// Relies on the Google APIs Client Library for .NET, v1.7.0 or higher.
  /// See https://developers.google.com/api-client-library/dotnet/get_started
  /// </summary>
  internal class UploadVideo
  {
    [STAThread]
    static void Main(string[] args)
    {
      Console.WriteLine("YouTube Data API: Upload Video");
      Console.WriteLine("==============================");

      try
      {
        new UploadVideo().Run().Wait();
      }
      catch (AggregateException ex)
      {
        foreach (var e in ex.InnerExceptions)
        {
          Console.WriteLine("Error: " + e.Message);
        }
      }

      Console.WriteLine("Press any key to continue...");
      Console.ReadKey();
    }

    private 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 = @"REPLACE_ME.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();
      }
    }

    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;
      }
    }

    void videosInsertRequest_ResponseReceived(Video video)
    {
      Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
    }
  }
}

Ruby

En esta muestra, se llama al método videos.insert de la API para subir un video al canal asociado con la solicitud.

En este ejemplo se utiliza la biblioteca cliente Ruby.

#!/usr/bin/ruby

require 'rubygems'
gem 'google-api-client', '>0.7'
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/file_storage'
require 'google/api_client/auth/installed_app'
require 'trollop'

# A limited OAuth 2 access scope that allows for uploading files, but not other
# types of account access.
YOUTUBE_UPLOAD_SCOPE = 'https://www.googleapis.com/auth/youtube.upload'
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'

def get_authenticated_service
  client = Google::APIClient.new(
    :application_name => $PROGRAM_NAME,
    :application_version => '1.0.0'
  )
  youtube = client.discovered_api(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION)

  file_storage = Google::APIClient::FileStorage.new("#{$PROGRAM_NAME}-oauth2.json")
  if file_storage.authorization.nil?
    client_secrets = Google::APIClient::ClientSecrets.load
    flow = Google::APIClient::InstalledAppFlow.new(
      :client_id => client_secrets.client_id,
      :client_secret => client_secrets.client_secret,
      :scope => [YOUTUBE_UPLOAD_SCOPE]
    )
    client.authorization = flow.authorize(file_storage)
  else
    client.authorization = file_storage.authorization
  end

  return client, youtube
end

def main
  opts = Trollop::options do
    opt :file, 'Video file to upload', :type => String
    opt :title, 'Video title', :default => 'Test Title', :type => String
    opt :description, 'Video description',
          :default => 'Test Description', :type => String
    opt :category_id, 'Numeric video category. See https://developers.google.com/youtube/v3/docs/videoCategories/list',
          :default => 22, :type => :int
    opt :keywords, 'Video keywords, comma-separated',
          :default => '', :type => String
    opt :privacy_status, 'Video privacy status: public, private, or unlisted',
          :default => 'public', :type => String
  end

  if opts[:file].nil? or not File.file?(opts[:file])
    Trollop::die :file, 'does not exist'
  end

  client, youtube = get_authenticated_service

  begin
    body = {
      :snippet => {
        :title => opts[:title],
        :description => opts[:description],
        :tags => opts[:keywords].split(','),
        :categoryId => opts[:category_id],
      },
      :status => {
        :privacyStatus => opts[:privacy_status]
      }
    }

    videos_insert_response = client.execute!(
      :api_method => youtube.videos.insert,
      :body_object => body,
      :media => Google::APIClient::UploadIO.new(opts[:file], 'video/*'),
      :parameters => {
        :uploadType => 'resumable',
        :part => body.keys.join(',')
      }
    )

    videos_insert_response.resumable_upload.send_all(client)

    puts "Video id '#{videos_insert_response.data.id}' was successfully uploaded."
  rescue Google::APIClient::TransmissionError => e
    puts e.result.body
  end
end

main

Errores

En la siguiente tabla, se identifican los mensajes de error que la API podría mostrar en respuesta a una llamada a este método. Consulta la documentación sobre mensajes de error para obtener más información.

Tipo de error Detalle del error Descripción
badRequest (400) defaultLanguageNotSet La solicitud intenta agregar detalles de video localizados sin especificar el idioma predeterminado de los detalles del video.
badRequest (400) invalidCategoryId La propiedad snippet.categoryId especifica un ID de categoría no válido. Usa el método videoCategories.list para recuperar las categorías admitidas.
badRequest (400) invalidDescription Los metadatos de la solicitud especifican una descripción del video no válida.
badRequest (400) invalidFilename El nombre de archivo de video especificado en el encabezado Slug no es válido.
badRequest (400) invalidPublishAt Los metadatos de la solicitud especifican una hora de publicación programada no válida.
badRequest (400) invalidRecordingDetails El objeto recordingDetails en los metadatos de la solicitud especifica detalles de grabación no válidos.
badRequest (400) invalidTags Los metadatos de la solicitud especifican palabras clave de video no válidas.
badRequest (400) invalidTitle Los metadatos de la solicitud especifican un título de video no válido o vacío.
badRequest (400) invalidVideoGameRating Los metadatos de la solicitud especifican una calificación de videojuego no válida.
badRequest (400) invalidVideoMetadata Los metadatos de la solicitud no son válidos.
badRequest (400) mediaBodyRequired La solicitud no incluye el contenido del video.
badRequest (400) uploadLimitExceeded El usuario superó la cantidad de videos que puede subir.
forbidden (403) forbidden
forbidden (403) forbiddenLicenseSetting La solicitud intenta establecer una licencia no válida para el video.
forbidden (403) forbiddenPrivacySetting La solicitud intenta establecer una configuración de privacidad no válida para el video.

Pruébalo

Usa el APIs Explorer para llamar a esta API y ver la solicitud a la API y la respuesta.