Videos: insert

2020년 7월 28일 이후에 생성된 인증되지 않은 API 프로젝트에서 videos.insert 엔드포인트를 통해 업로드된 모든 동영상은 비공개 보기 모드로 제한됩니다. 이 제한을 해제하려면 각 API 프로젝트가 서비스 약관의 준수 여부를 확인하는 감사를 받아야 합니다. 자세한 내용은 API 업데이트 기록을 참고하세요.

YouTube에 동영상을 업로드하고 동영상의 메타데이터를 선택적으로 설정합니다.

이 메서드는 미디어 업로드를 지원합니다. 업로드한 파일은 다음 제한사항을 따라야 합니다.

  • 최대 파일 크기: 256GB
  • 허용되는 미디어 MIME 유형: video/*, application/octet-stream

할당량 영향: 이 메서드에 대한 호출의 할당량 비용은 1,600단위입니다.

일반적인 사용 사례

요청

HTTP 요청

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

승인

이 요청에는 다음 범위 중 최소 하나를 사용하여 인증이 필요합니다. (인증 및 승인에 대해 자세히 알아보기)

범위
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 매개변수는 이 작업에서 두 가지 용도로 사용됩니다. 쓰기 작업에 설정할 속성과 API 응답에 포함될 속성을 식별합니다.

동영상을 삽입하거나 업데이트할 때 설정할 수 있는 속성이 모든 부분에 포함되는 것은 아닙니다. 예를 들어 statistics 객체는 YouTube가 동영상에 대해 계산하는 통계를 캡슐화하며 사용자가 설정하거나 수정할 수 있는 값은 포함하지 않습니다. 매개변수 값이 변경 가능한 값을 포함하지 않는 part를 지정하는 경우에도 part가 API 응답에 포함됩니다.

다음 목록에는 매개변수 값에 포함할 수 있는 part 이름이 포함되어 있습니다.
  • contentDetails
  • fileDetails
  • id
  • liveStreamingDetails
  • localizations
  • player
  • processingDetails
  • recordingDetails
  • snippet
  • statistics
  • status
  • suggestions
  • topicDetails
선택적 매개변수
notifySubscribers boolean
notifySubscribers 매개변수는 YouTube에서 동영상 채널을 구독하는 사용자에게 새 동영상에 대한 알림을 보내야 하는지 여부를 나타냅니다. 매개변수 값 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

응답

성공하는 경우 이 메소드는 응답 본문에 video 리소스를 반환합니다.

참고: 다음 코드 샘플은 지원되는 일부 프로그래밍 언어를 나타내지 않을 수 있습니다. 지원되는 언어 목록은 클라이언트 라이브러리 문서를 참고하세요.

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 요청 및 응답을 확인하세요.