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
  • 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
    • recordingDetails.locationDescriptionサポート終了
    • recordingDetails.location.latitudeサポート終了
    • recordingDetails.location.longitudeサポート終了
    • 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 メソッドを呼び出して、リクエストに関連付けられているチャンネルに動画をアップロードします。

This example uses the .NET client library.

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 のリクエストとレスポンスを確認します。