Using the google-apis-youtube_v3 gem I can upload a video, delete a video, insert captions, delete captions, and set a thumbnail image. The only thing that that for some reason does not work is the update_video
call, which always returns an error.
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'google-apis-youtube_v3'
REDIRECT_URI = 'http://localhost'
APPLICATION_NAME = '...'
API_KEY = '...'
SCOPE = Google::Apis::YoutubeV3::AUTH_YOUTUBE_FORCE_SSL
def authorize
client_id = Google::Auth::ClientId.from_file('secrets/client_secret.json')
token_store = Google::Auth::Stores::FileTokenStore.new(file: "secrets/youtube-creds.yml")
authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
user_id = 'default'
credentials = authorizer.get_credentials(user_id)
if credentials.nil?
url = authorizer.get_authorization_url(base_url: REDIRECT_URI)
puts "Open the following URL in the browser and enter the resulting code after authorization"
puts url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(user_id: user_id, code: code, base_url: REDIRECT_URI)
end
credentials
end
def get_service
service = Google::Apis::YoutubeV3::YouTubeService.new
service.key = API_KEY
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
service
end
o = {
"id": 'XYZ123',
"snippet": {
"category_id": "27",
"default_language": "en",
"description": "Testing updating description and title.",
"tags": [
"tag1",
"tag2",
"tag3"
],
"title": "Test video upload using Ruby SDK"
},
"status": {
"privacy_status": "private"
}
}
resp = s.update_video('id,snippet,status', o)
ArgumentError (unknown keywords: :id, :snippet, :status)
Note that the video object is almost identical to the one used to create the video in the first place. The only change, apart from trivial modifications of the video title and description, was the addition of the id
attribute to identify the video.
Jim Gay solved the problem in his comment. The ArgumentError is not, as I thought, thrown by the YouTube API gem. It's a Ruby exception thrown before the API method can be called.
The problem is that the second parameter to the method defaults to nil, so if you pass in the video object as a plain hash and it happens to be both the second and the last parameter in the method call, it will be interpreted by Ruby as a collection of keyword (named) parameters and not as the single value to be passed to the second argument. So :id
, :snippet
and :status
are not recognized as valid parameters since the method signature does not declare them.
This was not a problem with the insert_video
API call, since there in addition to the video object you most likely have to pass in the location of the video file as one of the named parameters.
As Jim indicated, you can construct a Google::Apis::YoutubeV3::Video
object and pass that in as the second/last argument with no ambiguity. The only inconvenience there is that you would also have to construct the video snippet and status objects inside the video object.
Another possibility is first to fetch the video object from YouTube using the list_videos
API call, edit the values as needed, and then pass it to update_video
.
The simplest thing, though, is just to pass the video object as a plain hash, but also pass in an actual named parameter to let Ruby know that the second argument is not supposed to be unpacked before passing it in. For example:
resp = s.update_video('id,snippet,status', o, options: nil)