Videos: insert

2020 年 7 月 28 日以降に作成された未確認の API プロジェクトの videos.insert エンドポイントからアップロードされた動画はすべて、非公開の視聴モードに制限されます。この制限を解除するには、各 API プロジェクトで監査を受け利用規約への準拠を確認する必要があります。詳しくは、API の変更履歴をご覧ください。

YouTube に動画をアップロードし、オプションで動画のメタデータを設定します。

このメソッドはメディア アップロードをサポートしています。アップロードするファイルには、以下の制約が適用されます。

  • 最大ファイルサイズ: 256 GB
  • 有効なメディア MIME タイプ: video/*application/octet-stream

割り当ての影響: このメソッドを呼び出すと、割り当てコストが 1,600 ユニットになります。

一般的なユースケース

リクエスト

HTTP リクエスト

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

承認

このリクエストは、少なくとも次のうち 1 つのスコープでの承認が必要です(認証と承認の詳細をご確認ください)。

スコープ
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

パラメータ

次の表に、このクエリでサポートされているパラメータを示します。このリストのパラメータはすべてクエリ パラメータです。

パラメータ
必須パラメータ
part string
part パラメータは、このオペレーションで 2 つの目的を果たします。書き込みオペレーションで設定されるプロパティと、API レスポンスに含まれるプロパティを特定します。

すべてのパートに、動画の挿入または更新時に設定できるプロパティが含まれているわけではありません。たとえば、statistics オブジェクトは、YouTube が動画に対して計算する統計情報をカプセル化します。設定または変更できる値は含まれません。パラメータ値で変更可能な値を含まない part を指定した場合でも、その part は API レスポンスに含まれます。

パラメータ値に含めることができる part 名を次の表に示します。
  • contentDetails
  • fileDetails
  • id
  • liveStreamingDetails
  • localizations
  • paidProductPlacementDetails
  • player
  • processingDetails
  • recordingDetails
  • snippet
  • statistics
  • status
  • suggestions
  • topicDetails
オプション パラメータ
notifySubscribers boolean
notifySubscribers パラメータは、動画のチャンネルを登録しているユーザーに新しい動画に関する通知を送信するかどうかを指定します。パラメータ値が True の場合、新しくアップロードされた動画がチャンネル登録者に通知されます。ただし、多くの動画をアップロードしているチャンネル所有者は、新しい動画ごとにチャンネル登録者に通知が送信されないように、値を False に設定することをおすすめします。デフォルト値は True です。
onBehalfOfContentOwner string
このパラメータは、適切に承認されたリクエストでのみ使用できます。注: このパラメータは YouTube コンテンツ パートナー専用です。

onBehalfOfContentOwner パラメータは、リクエストの認証情報が、パラメータ値で指定されたコンテンツ所有者の代理を務める YouTube CMS ユーザーを識別することを示します。このパラメータは、複数の YouTube チャンネルを所有、管理している YouTube コンテンツ パートナーを対象にしています。このパラメータを使用すると、コンテンツ所有者は一度認証されれば、すべての動画やチャンネル データにアクセスできるようになります。チャンネルごとに認証情報を指定する必要はありません。ユーザー認証に使用する CMS アカウントは、指定された YouTube コンテンツ所有者にリンクされていなければなりません。
onBehalfOfContentOwnerChannel string
このパラメータは、適切に承認されたリクエストでのみ使用できます。このパラメータは、適切に承認されたリクエストでのみ使用できます。注: このパラメータは YouTube コンテンツ パートナー専用です。

onBehalfOfContentOwnerChannel パラメータには、動画を追加するチャンネルの YouTube チャンネル ID を指定します。このパラメータは、リクエストで onBehalfOfContentOwner パラメータの値を指定する場合に必須です。このパラメータは、そのパラメータと組み合わせてのみ使用できます。また、onBehalfOfContentOwner パラメータで指定されたコンテンツ所有者にリンクされている CMS アカウントを使用してリクエストを承認する必要があります。最後に、onBehalfOfContentOwnerChannel パラメータ値で指定したチャンネルは、onBehalfOfContentOwner パラメータで指定したコンテンツ所有者にリンクされている必要があります。

このパラメータは、さまざまな YouTube チャンネルを所有して管理している YouTube コンテンツ パートナーを対象としています。このパラメータを使用すると、コンテンツ所有者は一度認証されれば、パラメータ値で指定されたチャンネルの代わりにアクションを実行できるようになります。チャンネルごとに認証情報を指定する必要はありません。

リクエスト本文

リクエストの本文に動画リソースを指定します。リソースに対して以下の操作を行います。

  • 以下のプロパティの値を指定することができます。

    • 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
    • status.containsSyntheticMedia
    • recordingDetails.recordingDate

レスポンス

成功すると、このメソッドはレスポンスの本文で動画のリソースを返します。

注: 次のコードサンプルは、サポートされているプログラミング言語のすべてを網羅しているわけではありません。サポートされている言語の一覧については、クライアント ライブラリのドキュメントをご覧ください。

Go

このコードサンプルは、API の videos.insert メソッドを呼び出して、リクエストに関連付けられたチャンネルに動画をアップロードします。

この例では、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

次のコードサンプルは、API の videos.insert メソッドを呼び出して、リクエストに関連付けられたチャンネルに動画をアップロードします。

この例では、.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

このサンプルでは、API の videos.insert メソッドを呼び出して、リクエストに関連付けられたチャンネルに動画をアップロードします。

この例では、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

エラー

次の表に、このメソッドの呼び出しへのレスポンスとして API から返されるエラー メッセージを示します。詳細については、エラー メッセージのドキュメントを参照してください。

エラーのタイプ エラーの詳細 説明
badRequest (400) defaultLanguageNotSet リクエストで、動画の詳細のデフォルトの言語を指定せずに、ローカライズされた動画の詳細を追加しようとしています。
badRequest (400) invalidCategoryId snippet.categoryId プロパティに無効なカテゴリ ID が指定されています。サポートされているカテゴリを取得するには、videoCategories.list メソッドを使用します。
badRequest (400) invalidDescription リクエスト メタデータで指定された動画の説明は無効です。
badRequest (400) invalidFilename Slug ヘッダーで指定された動画ファイル名が無効です。
badRequest (400) invalidPublishAt リクエスト メタデータで、無効なスケジュール設定された公開時間が指定されています。
badRequest (400) invalidRecordingDetails リクエスト メタデータの recordingDetails オブジェクトに、無効な録画の詳細が指定されています。
badRequest (400) invalidTags リクエスト メタデータで指定された動画のキーワードは無効です。
badRequest (400) invalidTitle リクエスト メタデータで、無効な動画タイトルまたは空の動画タイトルが指定されています。
badRequest (400) invalidVideoGameRating リクエスト メタデータで指定されたビデオ ゲームの評価は無効です。
badRequest (400) invalidVideoMetadata リクエスト メタデータが無効です。
badRequest (400) mediaBodyRequired リクエストに動画コンテンツが含まれていません。
badRequest (400) uploadLimitExceeded アップロードできる動画の数が上限を超えました。
forbidden (403) forbidden
forbidden (403) forbiddenLicenseSetting リクエストは、動画に無効なライセンスを設定しようとしています。
forbidden (403) forbiddenPrivacySetting リクエストは、動画に無効なプライバシー設定を指定しようとしています。

試してみよう:

APIs Explorer を使用してこの API を呼び出し、API リクエストとレスポンスを確認します。