2014-12-22 106 views
1

我的目標是讓我的應用程序用戶通過我的服務器上傳到我的YouTube帳戶。 我有一個開發人員帳戶,啓用了YouTube數據api和一個服務帳戶客戶端設置,由於某種原因我沒有授權。我通過網絡挖掘,試圖找出原因並發現許多事情。 我試圖在管理員安全設置中給項目客戶端ID和範圍授予權限。 很多人都說這個錯誤是由於我沒有與我的帳戶關聯的YouTube帳戶造成的。但我不知道如何關聯這些。如何通過ruby服務帳戶插入視頻youtube api v3

這是我upload_video.rb腳本:

require 'rubygems' 
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 'certified' 

DEVELOPER_KEY = "MY-DEVELOPER-KEY" 
YOUTUBE_UPLOAD_SCOPE = 'https://www.googleapis.com/auth/youtube.upload' 
YOUTUBE_API_SERVICE_NAME = 'youtube' 
YOUTUBE_API_VERSION = 'v3' 

def get_authenticated_service 
    puts @PROGRAM_NAME 
    client = Google::APIClient.new(
    :application_name => $PROGRAM_NAME, 
    :application_version => '1.0.0' 
) 

key = Google::APIClient::KeyUtils.load_from_pkcs12('oauth2service.p12', 'notasecret') 
    auth_client = Signet::OAuth2::Client.new(
    :token_credential_uri => 'https://accounts.google.com/o/oauth2/token', 
    :audience => 'https://accounts.google.com/o/oauth2/token', 
    :scope => YOUTUBE_UPLOAD_SCOPE, 
    :issuer => 'SERVICE ACCOUNT EMAIL ADDRESS', 
    :signing_key => key) 
auth_client.fetch_access_token! 
client.authorization = auth_client 
youtube = client.discovered_api(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION) 
return client, youtube 
end 

def upload2youtube file, title, description, category_id, keywords, privacy_status 

    client, youtube = get_authenticated_service 
    begin 
    body = { 
    :snippet => { 
    :title => title, 
    :description => description, 
    :tags => keywords.split(','), 
    :categoryId => category_id, 
    }, 
    :status => { 
    :privacyStatus => privacy_status 
    } 
} 

videos_insert_response = client.execute!(
    :api_method => youtube.videos.insert, 
    :body_object => body, 
    :media => Google::APIClient::UploadIO.new(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 

這是我如何從另一個腳本運行它:

require 'google/api_client' 
require_relative 'upload_video' 

$PROGRAM_NAME = 'MY-PROJECT-NAME' 
upload2youtube File.open("somevideo.avi"), "title", "description", 'categoryid', 'tag1,tag2,tag3', 'unlisted' 

這是結果:

{ 
"error": { 
    "errors": [ 
    { 
    "domain": "youtube.header", 
    "reason": "youtubeSignupRequired", 
    "message": "Unauthorized", 
    "locationType": "header", 
    "location": "Authorization" 
    } 
    ], 
    "code": 401, 
    "message": "Unauthorized" 
} 
} 

我在做什麼錯了

回答

1
#!/usr/bin/ruby 

require 'rubygems' 
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 'certified' 


class Youtube_Helper 

    @@client_email = '' #email id from service account (that really long email address...) 
    @@youtube_email = '' #email associated with youtube account 
    @@p12_file_path = '' #path to the file downloaded from the service account (Generate new p12 key button) 
    @@p12_password = '' # password to the file usually 'notasecret' 
    @@api_key = nil # The API key for non authenticated things like lists 
    YOUTUBE_UPLOAD_SCOPE = 'https://www.googleapis.com/auth/youtube.upload' 
    YOUTUBE_API_SERVICE_NAME = 'youtube' 
    YOUTUBE_API_VERSION = 'v3' 
    @@client = nil 
    @@youtube = nil 
    FILE_POSTFIX = '-oauth2.json' 

    def initialize(client_email, youtube_email, p12_file_path, p12_password, api_key) 
    @@client_email=client_email 
    @@youtube_email=youtube_email 
    @@p12_file_path=p12_file_path 
    @@p12_password=p12_password 
    @@api_key = api_key 
    end 

    def get_authenticated_service 


    credentialsFile = $0 + FILE_POSTFIX 

    needtoauthenticate = false 

    @api_client = Google::APIClient.new(
     :application_name => $PROGRAM_NAME, 
     :application_version => '1.0.0' 
    ) 

    key = Google::APIClient::KeyUtils.load_from_pkcs12(@@p12_file_path, @@p12_password) 
    @auth_client = Signet::OAuth2::Client.new(
     :token_credential_uri => 'https://accounts.google.com/o/oauth2/token', 
     :audience => 'https://accounts.google.com/o/oauth2/token', 
     :scope => YOUTUBE_UPLOAD_SCOPE, 
     :issuer => @@client_email, 
     :person => @@youtube_email, 
     :signing_key => key) 


    if File.exist? credentialsFile 
     puts 'credential file exists' 
     puts credentialsFile.to_s 
     File.open(credentialsFile, 'r') do |file| 
     credentials = JSON.load(file) 
     if !credentials.nil? 
      puts 'get credentials from file' 
      @auth_client.access_token = credentials['access_token'] 
      @auth_client.client_id = credentials['client_id'] 
      @auth_client.client_secret = credentials['client_secret'] 
      @auth_client.refresh_token = credentials['refresh_token'] 
      @auth_client.expires_in = (Time.parse(credentials['token_expiry']) - Time.now).ceil 
      @api_client.authorization = @auth_client 
      if @auth_client.expired? 
      puts 'authorization expired' 
      needtoauthenticate = true 
      end 
     else 
      needtoauthenticate = true 
     end 
     end 
    else 
     needtoauthenticate = true 
    end 

    if needtoauthenticate 
     @auth_client.fetch_access_token! 
     @api_client.authorization = @auth_client 
     save(credentialsFile) 
    end 

    youtube = @api_client.discovered_api(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION) 
    @@client = @api_client 
    @@youtube = youtube 
    return @api_client, youtube 
    end 

    def save(credentialsFile) 
    File.open(credentialsFile, 'w', 0600) do |file| 
     json = JSON.dump({ 
     :access_token => @auth_client.access_token, 
     :client_id => @auth_client.client_id, 
     :client_secret => @auth_client.client_secret, 
     :refresh_token => @auth_client.refresh_token, 
     :token_expiry => @auth_client.expires_at 
     }) 
     file.write(json) 
    end 
    end 

    def upload2youtube file, title, description, category_id, keywords, privacy_status 
    puts 'begin' 
    begin 
     body = { 
     :snippet => { 
      :title => title, 
      :description => description, 
      :tags => keywords.split(','), 
      :categoryId => category_id, 
     }, 
     :status => { 
      :privacyStatus => privacy_status 
     } 
     } 
     puts body.keys.join(',') 

     # Call the API's videos.insert method to create and upload the video. 
     videos_insert_response = @@client.execute!(
     :api_method => @@youtube.videos.insert, 
     :body_object => body, 
     :media => Google::APIClient::UploadIO.new(file, 'video/*'), 
     :parameters => { 
      'uploadType' => 'multipart', 
      :part => body.keys.join(',') 
     } 
    ) 

     puts'inserted' 

     puts "'#{videos_insert_response.data.snippet.title}' (video id: #{videos_insert_response.data.id}) was successfully uploaded." 

    rescue Google::APIClient::TransmissionError => e 
     puts e.result.body 
    end 

    return videos_insert_response.data.id #video id 

    end 

    def upload_thumbnail video_id, thumbnail_file, thumbnail_size 
    puts 'uploading thumbnail' 
    begin 
     thumbnail_upload_response = @@client.execute({ :api_method => @@youtube.thumbnails.set, 
          :parameters => { :videoId => video_id, 
              'uploadType' => 'media', 
              :onBehalfOfContentOwner => @@youtube_email}, 
          :media => thumbnail_file, 
          :headers => { 'Content-Length' => thumbnail_size.to_s, 
              'Content-Type' => 'image/jpg' } 
          }) 
    rescue Google::APIClient::TransmissionError => e 
     puts e.result.body 
    end 
    end 

    def get_video_statistics video_id 
    client = Google::APIClient.new(:key => @@api_key, 
            :application_name => $PROGRAM_NAME, 
            :application_version => '1.0.0', 
            :authorization => nil) 
    youtube = client.discovered_api(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION) 
    stats_response = client.execute!(:api_method => youtube.videos.list, 
        :parameters => {:part => 'statistics', :id => video_id } 
        ) 
    return stats_response 
    end 
end 
+0

我得到 Signet :: AuthorizationError:授權失敗。服務器消息: { 「error」:「invalid_grant」 } – venkatareddy

+0

我更新了代碼現在試試吧 – dangalg

+0

@venkatareddy您現在嘗試了代碼嗎?我編輯它。請告訴我,如果它工作 – dangalg

相關問題