How to Insert Video Youtube API V3 Through Service Account with Ruby

How to insert video youtube api v3 through service account with ruby


#!/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

Using ruby google-api-client to get youtube video data

That wasn't so hard, I found out how to do it.

You don't need to deal with oAuth authentication in that case. You will need to generate a server API Key and send it on each request.

The following snippet will help retrieving all information about a video the API provides.

require 'google/api_client'
require 'json'

client = Google::APIClient.new

youtube = client.discovered_api('youtube', 'v3')

client.authorization = nil

result = client.execute :key => "<YOUR_SERVER_API_KEY>", :api_method => youtube.videos.list, :parameters => {:id => '<YOUR_VIDEO_ID>', :part => 'snippet'}

result = JSON.parse(result.data.to_json)

Ruby YouTube Data API v3 insert caption always returns error

I looked at the OVERVIEW.md file included with the google-apis-youtube_v3 gem, and it referred to the Google simple REST client Usage Guide, which in turn mentions that most object properties do not use camel case (which is what the underlying JSON representation uses). Instead, in most cases properties must be sent using Ruby's "snake_case" convention.

Thus it turns out that the snippet should specify video_id and not videoId.

That seems to have let the request go through, so this resolves this issue.

The response I'm getting now has a status of "failed" and a failure reason of "processingFailed", but that may be the subject of another question if I can't figure it out.

Google YouTube API v3 :: Server-to-Server Upload Service

First off, letting arbitrary users upload videos into a "master" YouTube channel is not recommended, for the reasons outlined in this blog post.

That being said, if you're determined to do it, then you need to include an access token associated with your channel in each upload request. The appropriate way to get a fresh access token (they expire after an hour) is to take a refresh token that you've previously generated and stored somewhere and make an HTTP request to the appropriate URL to get back an access token, as explained in the OAuth 2 documentation. There's no way around that—I'm not sure whether there's a native method in the Google APIs PHP client library that will automate the process for you, but that's what needs to happen under the hood.

The information in Google Calendar API v3 hardcoded credentials does seem relevant.

YouTube API v3 with OAuth2: update and delete fail with Insufficient Permission error

I'm fairly sure all 11 views of this question (as of this writing) are me, but I'm going to post an answer just in case it helps someone in the future:

There was no problem with my code itself. The problem was when I initially created my refresh_token for this account.

For the uninitiated, the YouTube Data API (v3) does not support "service accounts," which, elsewhere in the Google API ecosystem, are the way you would normally accomplish setting up an OAuth2 auth'd client when the only client is yourself. The workaround is something you have to do by hand. Take the steps below:


First, go to the Google "API Console." There, under "API Access," you need to "Create a client ID" for an "installed application." This will give you a Client ID, a Client secret and a Redirect URI (you'll want the non-localhost one). Write these down.

Next, you need to manually obtain an authorization code by visiting a URL like the following in your favorite web browser, while logged in to the same account you just created the client ID for:

https://accounts.google.com/o/oauth2/auth
?client_id={client_id}
&redirect_uri={redirect_uri}
&scope={space separated scopes}
&response_type=code
&access_type=offline

Of course, you need to enter the client_id, redirect_uri and scope query parameters. In my case, this is where I went wrong. When I did this manual step, I should have put the scope param as:

https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload

But instead I just did https://www.googleapis.com/auth/youtube.upload, which is insufficient to update/delete videos!

Last, you need to obtain a refresh_token, by taking a URL like this:

https://accounts.google.com/o/oauth2/token
?code={authorization_code}
&client_id={client_id}
&client_secret={client_secret}
&redirect_uri={redirect_uri}
&grant_type=authorization_code

And curl'ing it with a command like:

$ curl https://accounts.google.com/o/oauth2/token -d "code=..."

This will return a JSON response that contains your refresh_token, which you then use when authorizing your request programmatically through the Google API.

To upload Videos to youtube from Ruby on Rails app

It seems yt gem has upload support. Here is a full documentation for it: https://fullscreen.github.io/yt/accounts.html

Short summary from the link above:

Yt.configuration.client_id = "<your ID>"
Yt.configuration.client_secret = "<your secret>"
account = Yt::Account.new refresh_token: "<token>"

account.upload_video "http://example.com/remote_video.mp4", title: 'My video'

Which Youtube Data API auth method should I be using?

You should use the ClientLogin method.
For example, suppose you want to authenticate a YouTube account for which the username and password are testuser and testpassword, respectively. You can simulate the HTTP POST request using the Linux 'curl' command, as shown in the following example:

curl \
--location https://www.google.com/accounts/ClientLogin \
--data 'Email=testuser&Passwd=testpw&service=youtube&source=Test' \
--header 'Content-Type:application/x-www-form-urlencoded'

If your authentication request is successful, the response to your request will have the following format. (Please note that the token values have been shortened in the example.)

SID=DQAAALQAAAA6wx7byZp-s4BizDqS1OaT21j9dmY6wMjexpQdNC3
LSID=DQAAALUAAAARH_PvRXoaz23Dv_UmOSUz2_0vh-4XbUedCN9XTZ
Auth=DQAAALUAAAARH_PvRXoaz23Dv_UmOSUz2_jxJVCGjoulKlhWbU

When you make an authenticated API request using a ClientLogin authentication token, your request needs to specify the Authorization HTTP request header as shown in the example below:

Authorization: GoogleLogin auth=<authentication_token>
X-GData-Key: key=<developer_key>

Then you can use the token in the rest of your application, and lump all the uploaded content into one youtube username.

As for gems, theres active-youtube, youtube_g and a few others, however I haven't found any that really streamline the auth process. Most just allow you to query for top video feeds and stuff like that. A gem would make a good starting point though to build out the rest of your app. This completed upload script is a good starting point as well. Google's Authentication Docs



Related Topics



Leave a reply



Submit