i want to upload video to youtube channel.i tried with following Code.the bellow code work to upload video but the problem is, i can't attach its information(Video Title,Description & Tags).after uploading it shows only video title as a "unknown" and no tags or description .i've seen CodingTofu , Dev7Dev Blog- iOS Sample Code and many other Q&A but i can't understand where i'm making mistake.
NSString* title = video.title;
NSString* description = video.videoDescription;
NSData* data = video.data;
NSMutableArray* tags = video.tags.mutableCopy;
GTLYouTubeVideo *yVideo = [GTLYouTubeVideo object];
GTLYouTubeVideoSnippet *snippet = [GTLYouTubeVideoSnippet alloc];
snippet.title = title;
snippet.descriptionProperty = description;
[tags addObject:DEFAULT_KEYWORD];
NSString* tag = [UploadController generateKeywordFromPlaylistId:UPLOAD_PLAYLIST];
[tags addObject:tag];
snippet.tags = tags;
GTLYouTubeVideoStatus *status = [GTLYouTubeVideoStatus alloc];
status.privacyStatus = #"public";
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:data MIMEType:#"video/*"];
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosInsertWithObject:yVideo part:#"snippet,status" uploadParameters:uploadParameters];
service.uploadProgressBlock = ^(GTLServiceTicket* ticket, unsigned long long totalBytesUploaded, unsigned long long totalBytesExpectedToUpload){
CGFloat percentage = totalBytesUploaded/totalBytesExpectedToUpload;
NSLog(#"\nUploaded percentage %%(%0.2f)",percentage);
};
[service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLYouTubeVideo *insertedVideo, NSError *error) {
//[waitIndicator dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil)
{
NSLog(#"File ID: %#", insertedVideo.identifier);
return;
}
else
{
NSLog(#"An error occurred: %#", error);
return;
}
}];
tell me if you need any further Details
thank you.
sorry for my bad English.
i got the Mistake,
in above code, i have to add
GTLYouTubeVideo *yVideo = [GTLYouTubeVideo object];
GTLYouTubeVideoStatus *status = [GTLYouTubeVideoStatus alloc];
GTLYouTubeVideoSnippet *snippet = [GTLYouTubeVideoSnippet alloc];
*******
*******
*******
yVideo.snippet = snippet;//This part i forgot to add in my code
yVideo.status = status;//This part i forgot to add in my code
[service executeQuery........
This Might be helpful to someone who facing same issue.
Related
In my project wanna have a flow like this:
Users record short videos -> they upload the videos on my channel -> end
To achive this result i'm trying to work with the new Google APIs Client Library for Objective-C for REST. It has a poor documentation and the examples are for mac only. Anyway after many errors this is my code:
- (void)doAuthWithoutCodeExchange:(OIDServiceConfiguration *)configuration
clientID:(NSString *)clientID
clientSecret:(NSString *)clientSecret {
NSURL *redirectURI = [NSURL URLWithString:kRedirectURI];
// builds authentication request
OIDAuthorizationRequest *request =
[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
clientId:clientID
clientSecret:clientSecret
scopes:#[ OIDScopeOpenID, OIDScopeProfile ]
redirectURL:redirectURI
responseType:OIDResponseTypeCode
additionalParameters:nil];
// performs authentication request
AppDelegate *appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
[self logMessage:#"Initiating authorization request %#", request];
appDelegate.currentAuthorizationFlow =
[OIDAuthorizationService presentAuthorizationRequest:request
presentingViewController:self
callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse,
NSError *_Nullable error) {
if (authorizationResponse) {
OIDAuthState *authState =
[[OIDAuthState alloc] initWithAuthorizationResponse:authorizationResponse];
[self setAuthState:authState];
[self logMessage:#"Authorization response with code: %#",
authorizationResponse.authorizationCode];
// could just call [self tokenExchange:nil] directly, but will let the user initiate it.
OIDTokenRequest *tokenExchangeRequest =
[_authState.lastAuthorizationResponse tokenExchangeRequest];
[self logMessage:#"Performing authorization code exchange with request [%#]",
tokenExchangeRequest];
[OIDAuthorizationService performTokenRequest:tokenExchangeRequest
callback:^(OIDTokenResponse *_Nullable tokenResponse,
NSError *_Nullable error) {
if (!tokenResponse) {
[self logMessage:#"Token exchange error: %#", [error localizedDescription]];
} else {
[self logMessage:#"Received token response with accessToken: %#", tokenResponse.accessToken];
}
[_authState updateWithTokenResponse:tokenResponse error:error];
GTMAppAuthFetcherAuthorization *gtmAuthorization =
[[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState];
// Sets the authorizer on the GTLRYouTubeService object so API calls will be authenticated.
self.youTubeService.authorizer = gtmAuthorization;
// Serializes authorization to keychain in GTMAppAuth format.
[GTMAppAuthFetcherAuthorization saveAuthorization:gtmAuthorization
toKeychainForName:kGTMAppAuthKeychainItemName];
[self uploadVideoFile];
}];
} else {
[self logMessage:#"Authorization error: %#", [error localizedDescription]];
}
}];
}
This method cause this flow:
app send user to google login page in safari -> user log with his credentials -> after login, user is redirect back to my app -> the block success call the method UploadVideo.
This part of the flow seems to work correctly, i obtain a valid token as the log says. The second part is the video upload that consist in two main methods:
- (void)uploadVideoFile {
// Collect the metadata for the upload from the user interface.
// Status.
GTLRYouTube_VideoStatus *status = [GTLRYouTube_VideoStatus object];
status.privacyStatus = #"public";
// Snippet.
GTLRYouTube_VideoSnippet *snippet = [GTLRYouTube_VideoSnippet object];
snippet.title = #"title";
NSString *desc = #"description";
if (desc.length > 0) {
snippet.descriptionProperty = desc;
}
NSString *tagsStr = #"tags";
if (tagsStr.length > 0) {
snippet.tags = [tagsStr componentsSeparatedByString:#","];
}
GTLRYouTube_Video *video = [GTLRYouTube_Video object];
video.status = status;
video.snippet = snippet;
[self uploadVideoWithVideoObject:video
resumeUploadLocationURL:nil];
}
- (void)uploadVideoWithVideoObject:(GTLRYouTube_Video *)video
resumeUploadLocationURL:(NSURL *)locationURL {
NSURL *fileToUploadURL = [NSURL fileURLWithPath:self.VideoUrlCri.path];
NSError *fileError;
NSLog(#"step");
if (![fileToUploadURL checkPromisedItemIsReachableAndReturnError:&fileError]) {
NSLog(#"exit");
return;
}
// Get a file handle for the upload data.
NSString *filename = [fileToUploadURL lastPathComponent];
NSString *mimeType = [self MIMETypeForFilename:filename
defaultMIMEType:#"video/mp4"];
GTLRUploadParameters *uploadParameters =
[GTLRUploadParameters uploadParametersWithFileURL:fileToUploadURL
MIMEType:mimeType];
uploadParameters.uploadLocationURL = locationURL;
GTLRYouTubeQuery_VideosInsert *query =
[GTLRYouTubeQuery_VideosInsert queryWithObject:video
part:#"snippet,status"
uploadParameters:uploadParameters];
query.executionParameters.uploadProgressBlock = ^(GTLRServiceTicket *ticket,
unsigned long long numberOfBytesRead,
unsigned long long dataLength) {
NSLog(#"upload progress");
};
GTLRYouTubeService *service = self.youTubeService;
_uploadFileTicket = [service executeQuery:query
completionHandler:^(GTLRServiceTicket *callbackTicket,
GTLRYouTube_Video *uploadedVideo,
NSError *callbackError) {
if (callbackError == nil) {
NSLog(#"uploaded");
} else {
NSLog(#"error %#",callbackError);
}
}];
}
- (NSString *)MIMETypeForFilename:(NSString *)filename
defaultMIMEType:(NSString *)defaultType {
NSString *result = defaultType;
NSString *extension = [filename pathExtension];
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
(__bridge CFStringRef)extension, NULL);
if (uti) {
CFStringRef cfMIMEType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);
if (cfMIMEType) {
result = CFBridgingRelease(cfMIMEType);
}
CFRelease(uti);
}
return result;
}
I obtain a 403 error in NSLog(#"error %#",callbackError); and i can't see error details because the are something like :
data=<7b226572 726f7222 3a7b2265 72726f72 73223a5b 7b22646f 6d61696e 223a2267 6c6f6261 6c222c22 72656173 6f6e223a 22696e73 75666669 ... 61676522 3a22496e 73756666 69636965 6e742050 65726d69 7373696f 6e227d7d>}
In google api console i have created a Client Oauth for my application bundle and an API key, i use those values for my connection, it seems they works correctly because i obtain a valid token. Anyway, there someone who can help me or point me in the right direction about this error? Or there someone who knows a working example about a video upload for IOS and not for MAC ? There something weird in my code? I can't find any help in documentation or google
I would like to know the best way to get passed the video maxResults. I can't set it past 50. I need to get about 207 videos right now. This list will continue to grow over time.
Do you have any suggestions on how I would do this?
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
service.APIKey = #"API Key";
service.shouldFetchInBackground = YES;
GTLQueryYouTube *query = [GTLQueryYouTube queryForPlaylistItemsListWithPart:#"snippet,contentDetails"];
query.playlistId = #"Playlist ID";
query.maxResults = 50;
GTLServiceTicket *ticket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
// This callback block is run when the fetch completes
if (error == nil)
{
GTLYouTubeSearchListResponse *products = object;
GTLYouTubePlaylistItemListResponse *playlistItems = object;
for (GTLYouTubeSearchResult *item in products)
{
GTLYouTubeThumbnailDetails *thumbnails = item.snippet.thumbnails;
GTLYouTubeThumbnail *thumbnail = thumbnails.high;
NSString *thumbnailString = thumbnail.url;
if (thumbnailString != nil)
{
[self.thumbnailsURL addObject:thumbnailString];
[self.thumbnailsArray addObject:thumbnailString];
[self.thumbnailImages addObject:#"120x120#2x.png"];
[self.thumbnailTitleArray addObject:item.snippet.title];
}
}
for (GTLYouTubePlaylistItem *playlistItem in playlistItems)
{
GTLYouTubePlaylistItemContentDetails *details = playlistItem.contentDetails;
[self.videos addObject:details.videoId];
}
}
else
{
NSLog(#"Error: %#", error.description);
}
self.loading.hidden = YES;
[self.tableView reloadData];
}];
Thank you in advance for your time! :D
You'll get the rest of the results with using paging.
YouTube API supports pagination. You need to put your nextPageToken in your next request as pageToken to get the next page(50 in your case) of results.
These 2 answers of mine should help you:
page tokens use youtube api v3
Retrieve all videos from youtube playlist using youtube v3 API
I have added youtube api v3 using google api's objective-C client in my app to upload video to youtube. Testers of the app (in different country) reports that they are unable to upload video to youtube. Video uploading fails after reaching to 100 % progress with backend error. Where as I am not facing that issue in my end here in India. Testers also confirms that youtube video upload is working fine when uploaded using youtube ios app or some different app. They also tried uploading videos from multiple accounts but with same result.
The error log from device console is:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=-32099 "The operation couldn’t be completed. (Backend Error)" UserInfo=0x2438c380 {error=Backend Error, GTLStructuredError=GTLErrorObject 0x27ea3990: {message:"Backend Error" code:-32099 data:[1]}, NSLocalizedFailureReason=(Backend Error)}
and my code that I am using to upload video to youtube is:
GTMOAuth2Authentication *auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:YoutubeOAuthKeyChain clientID:GoogleAPIClientID clientSecret:GoogleAPIClientSecret];
if (!auth) {
[self signInToGoogle];
}else{
if ([auth canAuthorize] && auth.userEmail) {
//Force the api to refresh access token if needed
[auth authorizeRequest:Nil completionHandler:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
NSLog(#"Youtube: App authorized. Uploading video now");
self.youTubeService.authorizer = auth;
GTLYouTubeVideoStatus *status = [GTLYouTubeVideoStatus object];
status.privacyStatus = #"public";
GTLYouTubeVideoSnippet *snippet = [GTLYouTubeVideoSnippet object];
snippet.title = _captionTextView.text;
snippet.descriptionProperty = #"This is a test video";
GTLYouTubeVideo *video = [GTLYouTubeVideo object];
video.status = status;
video.snippet = snippet;
NSString *filename = [_moviePath lastPathComponent];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:_moviePath];
if (fileHandle) {
NSString *mimeType = [self MIMETypeForFilename:filename
defaultMIMEType:#"video/mp4"];
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithFileHandle:fileHandle MIMEType:mimeType];
uploadParameters.uploadLocationURL = nil;
//uploadParameters.shouldSendUploadOnly = YES;
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosInsertWithObject:video part:#"snippet,status" uploadParameters:uploadParameters];
GTLServiceYouTube *service = self.youTubeService;
GTLServiceTicket *ticket = [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
NSLog(#"Youtube video upload completed ");
}else{
NSLog(#"error completing request with error: %#", error);
}
});
}];
[ticket setUploadProgressBlock:^(GTLServiceTicket *ticket, unsigned long long totalBytesWritten, unsigned long long totalBytesExpectedToWrite) {
float progress = ((float)totalBytesWritten / (float)totalBytesExpectedToWrite) * 100.0f;
NSLog(#"%f %% uploaded");
}];
}
}else{
//Error authorizing the request
NSLog(#"error authorizing request with error: %#", error);
}
});
}];
}else{
//Refresh access token
[self signInToGoogle];
}
}
This issue started just 2 weeks ago. I have no idea if this is a server side issue of some issue with my app. Has anyone also have the same issue?
I am given a list of youtube IDs. For each of this IDS, I want to use the YouTube API to get the title, duration, and thumbnail. I then want the user to be able to click these thumbnails which takes them to a UIWebView where they can watch the video.
I'm really stuck on how I can actually create a video object from the ID. I dont really understand the process in given in Google's sample code, they get the title based on a playlist. I dont want it based on a playlist, I want it based on a stand-alone ID or URL.
Using a playlist query, the code uses:
if ([playlistID length] > 0) {
GTLServiceYouTube *service = self.youTubeService;
GTLQueryYouTube *query = [GTLQueryYouTube queryForPlaylistItemsListWithPart:#"snippet,contentDetails"];
query.playlistId = playlistID;
query.maxResults = 50;
_playlistItemListTicket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLYouTubePlaylistItemListResponse *playlistItemList,
NSError *error) {
// Callback
_playlistItemList = playlistItemList;
_playlistFetchError = error;
_playlistItemListTicket = nil;
[self updateUI];
}];
}
Which I understand, but looking through GTLQueryYouTube I cant see anything that relates to a single video.
Does anybody have any ideas? Thanks!
Eventually I used:
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
// Services which do not require sign-in may need an API key from the
service.APIKey = #"myKey";
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosListWithPart:#"id, snippet, fileDetails"];
query.identifier = #"xxxxxxxxxx, yyyyyyyyyy";
GTLServiceTicket *ticket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
// This callback block is run when the fetch completes
if (error == nil) {
GTLYouTubeSearchListResponse *products = object;
// iteration of items and subscript access to items.
for (GTLYouTubeSearchResult *item in products) {
//NSMutableDictionary *dictionary = [item JSONValueForKey:#"id"];
GTLYouTubeThumbnailDetails *thumbnails = item.snippet.thumbnails;
GTLYouTubeThumbnail *thumbnail = thumbnails.high;
[imageArray addObject:thumbnail.url];
[titleArray addObject:item.snippet.title];
//NSLog(#"id: %#", [dictionary objectForKey:#"videoId"]);
//NSLog(#"Title: %#", item.snippet.title);
}
}else{
NSLog(#"Error: %#", error.description);
}
[self.thumbnailView reloadData];
}];
So created a queryForVideosListWithPart using a list of video ids separated by comma
There are a lot of GData YouTube tutorials on how to upload a Video in an iOS App, but I didn't find one showing how to comment on a Video. So I read on the reference-page, just tried and so on but didn't find anything!
Does anyone know how to comment on a Video in an iOS App using the GData API?
Thanks
Use this methods in comment button
GDataEntryYouTubeVideo *video = (GDataEntryYouTubeVideo *)arrayData;
[self addCommentTitle:#"comment" text:commentField.text toVideo:video];
- (void)addCommentTitle:(NSString *)commentTitle
text:(NSString *)commentContent
toVideo:(GDataEntryYouTubeVideo *)entry {
GDataComment *commentObj = [entry comment];
GDataFeedLink *feedLink = [commentObj feedLink];
NSURL *feedURL = [feedLink URL];
if (feedURL) {
// fetch the comment feed for the video
GDataServiceGoogleYouTube *service = [self youTubeService];
[service setYouTubeDeveloperKey:devKey];
[service setAuthToken:[self getRequestToken]];
[service fetchFeedWithURL:feedURL completionHandler:^(GDataServiceTicket *ticket, GDataFeedBase *commentFeed,NSError *error) {
if (error == nil) {
GDataEntryYouTubeComment *newCommentEntry = [GDataEntryYouTubeComment commentEntry];
[newCommentEntry addContentValueDeclaration];
[newCommentEntry setTitleWithString:commentTitle];
[newCommentEntry setContentWithString:commentContent];
NSString *subString = [videoString substringWithRange: NSMakeRange(0, [videoString rangeOfString: #"?"].location)];
NSString *last=[subString lastPathComponent];
NSString *ss=#"http://gdata.youtube.com/feeds/api/videos/";
NSString *idd=#"/comments";
NSString *com=[NSString stringWithFormat:#"%#%#%#",ss,last,idd];
NSURL *postURL = [NSURL URLWithString:com ];
[service fetchEntryByInsertingEntry:newCommentEntry
forFeedURL:postURL
completionHandler:^(GDataServiceTicket *ticket, GDataEntryBase *entry, NSError *error) {
// callback
if (error == nil) {
NSLog(#"url.: succeeded ");
}
}];
}
}];
}
}
get Authentication token using login details
- (NSString*) getRequestToken {
// return your auth token as string
}