Share video on Twitter with Fabric API without composer iOS
Asked Answered
C

2

13

Video uploads via REST API for Twitter is available in january but no with Fabric framework: link!

Cooley answered 7/7, 2015 at 4:41 Comment(1)
If you have multiple segments, you can try this solution: https://mcmap.net/q/903907/-ios-swift-how-to-post-a-video-to-twitter-with-twitterkitPoriferous
C
20

According to the documentation necessary to make 3 calls with the commands: INIT, APPEND and FINALIZE.

-(void) shareOnTwitterWithVideo:(NSDictionary*) params{   
    NSString *text = params[@"text"];
    NSData* dataVideo = params[@"video"];
    NSString *lengthVideo = [NSString stringWithFormat:@"%d", [params[@"length"] intValue]];
    NSString* url = @"https://upload.twitter.com/1.1/media/upload.json";

    __block NSString *mediaID;

    if([[Twitter sharedInstance] session]){

        TWTRAPIClient *client = [[Twitter sharedInstance] APIClient];
        NSError *error;
        // First call with command INIT
        NSDictionary *message =  @{ @"status":text,
                                   @"command":@"INIT",
                                @"media_type":@"video/mp4",
                               @"total_bytes":lengthVideo};
        NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

        [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){

            if(!error){
                NSError *jsonError;
                NSDictionary *json = [NSJSONSerialization
                                      JSONObjectWithData:responseData
                                      options:0
                                      error:&jsonError];

                mediaID = [json objectForKey:@"media_id_string"];
                client = [[Twitter sharedInstance] APIClient];
                NSError *error;
                NSString *videoString = [dataVideo base64EncodedStringWithOptions:0];
                // Second call with command APPEND
                message = @{@"command" : @"APPEND",
                           @"media_id" : mediaID,
                      @"segment_index" : @"0",
                              @"media" : videoString};

                NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

                [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){

                    if(!error){
                        client = [[Twitter sharedInstance] APIClient];
                        NSError *error;
                        // Third call with command FINALIZE
                        message = @{@"command" : @"FINALIZE",
                                                  @"media_id" : mediaID};

                        NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

                        [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){

                            if(!error){
                                client = [[Twitter sharedInstance] APIClient];
                                NSError *error;
                                // publish video with status
                                NSString *url = @"https://api.twitter.com/1.1/statuses/update.json";
                                NSMutableDictionary *message = [[NSMutableDictionary alloc] initWithObjectsAndKeys:text,@"status",@"true",@"wrap_links",mediaID, @"media_ids", nil];
                                NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

                                [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){
                                    if(!error){
                                        NSError *jsonError;
                                        NSDictionary *json = [NSJSONSerialization
                                                              JSONObjectWithData:responseData
                                                              options:0
                                                              error:&jsonError];
                                        NSLog(@"%@", json);
                                    }else{
                                        NSLog(@"Error: %@", error);
                                    }
                                }];
                            }else{
                                NSLog(@"Error command FINALIZE: %@", error);
                            }
                        }];

                    }else{
                        NSLog(@"Error command APPEND: %@", error);
                    }
                }];

            }else{
                NSLog(@"Error command INIT: %@", error);
            }

        }];
    }
}
Cooley answered 7/7, 2015 at 4:41 Comment(11)
thanks @fechidal for the concise and up-to-date answer!Usia
@fechidal: Awesome.. works great! Too bad twitter themselves don't have this.Ernst
I'm getting an error on the APPEND ---> Error Domain=TWTRNetworkingErrorDomain Code=-1011 "Request failed: bad request (400)". Any ideas how I can troubleshoot this?Camlet
@Camlet Are you sure that receive a mediaID? and the videoString is your NSData video convert to string on base 64, Are you sure this?Cooley
@fechidal Yes, I do get a mediaID from the INIT response -> Response: { "expires_after_secs" = 86399; "media_id" = 660168523088433152; "media_id_string" = 660168523088433152; }, The video data does look like it is converted to a string correctly as well. I wish I was getting a more descriptive error message.Camlet
@Camlet I am facing the same issue. Did you get any solution ?Endoblast
@Rakesh Bhatt No I was never able to get this working. There is an answer in a question I posted about uploading video with a tweet that may be a solution but I have not had time to see if that solution solves the problem. #32790359Camlet
@Camlet Here I leave the API error codes: dev.twitter.com/overview/api/response-codes, Error 400 - Bad Request - The request was invalid or cannot be otherwise served. An accompanying error message will explain further. In API v1.1, requests without authentication are considered invalid and will yield this response.Cooley
Any swift solution? I did not receive answers to this post: #36249465 and did not find any relevant documentation to post a video to twitter with swiftFrippery
APPEND ---> Error Domain=TWTRNetworkingErrorDomain Code=-1011 "Request failed: bad request (400)" this error ocuurs when video size is greater than 30s. Video specifications and recommendations when upload video :- dev.twitter.com/rest/media/uploading-mediaFervent
@Sam, I've answered you here: https://mcmap.net/q/903907/-ios-swift-how-to-post-a-video-to-twitter-with-twitterkit. It works ok for Swift 4 and for latest TwitterKit (3.3.0).Poriferous
G
11

Great answer, had some fun converting it into swift, took me a while so here is it for anyone else having the same issue:

var video: NSData!
let strUploadUrl = "https://upload.twitter.com/1.1/media/upload.json"
let strStatusUrl = "https://api.twitter.com/1.1/statuses/update.json"

func postVideo() {
    var client = Twitter.sharedInstance().APIClient
    var text: String = "Testing Video"
    var videoLength: String = "\(self.video.length)" 
    var mediaID: String = ""

    var initError: NSError? 
    var message = ["status": text, "command" : "INIT", "media_type" : "video/m4v", "total_bytes" : videoLength]
    var preparedRequest: NSURLRequest = client.URLRequestWithMethod("POST", URL: self.strUploadUrl, parameters: message, error: &initError)
    client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
        if error == nil {
            var jsonError: NSError?
            var json: NSDictionary = (NSJSONSerialization.JSONObjectWithData(responseData!, options: nil, error: &jsonError) as? NSDictionary)!
            println(json)
            var mediaID = json.objectForKey("media_id_string") as! String

            client = Twitter.sharedInstance().APIClient
            var uploadError: NSError?
            var videoString = self.video.base64EncodedStringWithOptions(nil)
            message = ["command" : "APPEND", "media_id" : mediaID, "segment_index" : "0", "media" : videoString]
            var preparedRequest = client.URLRequestWithMethod("POST", URL: self.strUploadUrl, parameters: message, error: &uploadError)
            client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
                if error == nil {
                    client = Twitter.sharedInstance().APIClient
                    var finalizeError: NSError?
                    message = ["command":"FINALIZE", "media_id": mediaID]
                    var preparedRequest = client.URLRequestWithMethod("POST", URL: self.strUploadUrl, parameters: message, error: &finalizeError)
                    client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
                        if error == nil {
                            client = Twitter.sharedInstance().APIClient
                            var sendError: NSError?
                            var message = ["status": text, "wrap_links": "true", "media_ids": mediaID]
                            var updateMessage = NSMutableDictionary(dictionary: message)
                            var preparedRequest = client.URLRequestWithMethod("POST", URL: self.strStatusUrl, parameters: message , error: &sendError)
                            client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in

                            })
                        } else {
                            println("Command FINALIZE failed \n \(error!)")
                        }
                    })
                } else {
                    println("Command APPEND failed")
                }
            })
        } else {
            println("Command INIT failed")
        }
    })

}
Galangal answered 26/8, 2015 at 12:12 Comment(4)
@Galangal I have implemented same as yours but returning "Command APPEND failed" I don't know what wrong have I done? Please help me to resolve.Elsa
Before the println("Command APPEND failed") add in println(error) to give you a clearer idea of why the request is failingGalangal
@Galangal It is throwing error like this "Request failed: unauthorized (401)" UserInfo=0x7f9d00d61fc0 {NSErrorFailingURLKey=upload.twitter.com/1.1/media/upload.json, NSLocalizedDescription=Request failed: unauthorized (401), NSLocalizedFailureReason=Twitter API error : Could not authenticate you. (code 32)})"Elsa
This solution does not work anymore. Do you have an up to date solution? I did not receive answers to my post: #36249465 and did not find any relevant solution for swift 2Frippery

© 2022 - 2024 — McMap. All rights reserved.