Videos: insert

Todos los videos que se hayan subido mediante el extremo videos.insert desde proyectos de API sin verificar creados después del 28 de julio de 2020 estarán restringidos al modo de visualización privada. Para resolver esta restricción, cada proyecto de API debe realizar una auditoría a fin de verificar el cumplimiento de las Condiciones del Servicio. Consulta el historial de revisión de la API para obtener más detalles.

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 del archivo: 256 GB
  • Tipos MIME de los medios aceptados: video/*, application/octet-stream

Impacto en la cuota: Una llamada a este método tiene un costo de cuota de 1,600 unidades.

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 contiene estadísticas que YouTube calcula para un video y no contiene valores que se pueden establecer o modificar. Si el valor del parámetro especifica un part que no contiene valores mutables, ese part se incluirá en la respuesta de la API.

En la siguiente lista, se incluyen los nombres part que puedes incluir en el valor del parámetro:
  • contentDetails
  • fileDetails
  • id
  • liveStreamingDetails
  • localizations
  • 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. El valor del parámetro True indica que los suscriptores recibirán una notificación sobre los videos subidos recientemente. Sin embargo, es posible que el propietario de un canal que esté subiendo muchos videos prefiera configurar el valor como 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 utilizar en una solicitud autorizada debidamente. Nota: Este parámetro está dirigido 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 varios 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 utilizar en una solicitud autorizada debidamente. Este parámetro solo se puede utilizar en una solicitud autorizada debidamente. Nota: Este parámetro está dirigido 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 se debe autorizar mediante una cuenta de CMS que esté vinculada al propietario del contenido que se especifica en 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
    • status.publicStatsViewable
    • status.publishAt
    • status.selfDeclaredMadeForKids
    • recordingDetails.locationDescription (obsoleto)
    • recordingDetails.location.latitude (obsoleto)
    • recordingDetails.location.longitude (obsoleto)
    • 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 los siguientes ejemplos de código no representen todos los lenguajes de programación admitidos. Consulta la documentación sobre bibliotecas cliente para obtener una lista de los lenguajes admitidos.

Comienza a usarlo

Esta muestra de código llama al método videos.insert de la API para subir un video al canal asociado a la solicitud.

En este ejemplo, se usa la biblioteca cliente de 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

La siguiente muestra de código invoca el método videos.insert de la API para subir un video al canal asociado a 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 localizados del video sin especificar el idioma predeterminado.
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 compatibles.
badRequest (400) invalidDescription Los metadatos de la solicitud especifican una descripción del video no válida.
badRequest (400) invalidFilename El nombre del 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ébela.

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