Share videos on Twitter via iOS App
Asked Answered
S

6

5

Is it possible to share a video using SLRequest ?

I'm able to share Images using the same

SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:requestURL parameters:message];

if (isImage)
{
    NSData *data = UIImagePNGRepresentation(imgSelected);
    [postRequest addMultipartData:data withName:@"media" type:@"image/png" filename:@"TestImage.png"];
}

postRequest.account = account;

[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
    if (!error)
    {
        NSLog(@"Upload Sucess !");
    }
}];
Sociable answered 3/6, 2015 at 6:26 Comment(3)
Doing anything other than sending photos/text and URL's with the built in Social framework is only possible when you make a custom request. You can't use the popup tweet sheet.Cyanite
Follow this as a guideline for your POST request: dev.twitter.com/rest/reference/post/media/upload-chunkedCyanite
Also if you don't know how to send video data in a POST request, have a look at this SO answer - it works great! - https://mcmap.net/q/1402646/-uploading-video-with-iphoneCyanite
C
4

I have been reading through the Twitter Video upload API documentation and its really pretty simple. You basically need to make 3 POST requests to their API. The video you are uploading is also limited to 15 MB in size.

Uploads using this endpoint require at least 3 calls, one to initialize the request, which returns the media_id, one or more calls to append/upload binary or base64 encoded data, and one last call to finalize the upload and make the media_id usable with other resources.

So it works like this:

  • Request 1: Send a init request with the video size in bytes. This will return a Media ID number which we have to use in request 2 and 3.

  • Request 2: Use the returned Media ID number from request 1 to upload the video data.

  • Request 3: Once the video upload has finished, send a "FINALIZE" request back to the Twitter API. This lets the Twitter API know that all the chunks of the video file has finished uploading.

Note The Twitter API accepts video uploads in "chunks". So if your video file is quite big, you may want to split it up into more than one file and thus you will have to repeat "Request 2" more than once (not forgetting to increment the "segment_index" number each time).

I have had a go at coding this below. Try it and experiment around with it. I will update my answer later on to improve it too.

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 

    // Assign the mediatype to a string 
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

    // Check the media type string so we can determine if its a video
    if ([mediaType isEqualToString:@"public.movie"]) {

        NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
        NSData *webData = [NSData dataWithContentsOfURL:videoURL];

        // Get the size of the file in bytes.
        NSString *yourPath = [NSString stringWithFormat:@"%", videoURL];
        NSFileManager *man = [NSFileManager defaultManager];
        NSDictionary *attrs = [man attributesOfItemAtPath:yourPath error: NULL];
        UInt32 result = [attrs fileSize];

        //[self tweetVideoStage1:webData :result];
        [self tweetVideo:webData :result :1 :@"n/a"];
    }
}

-(void)tweetVideo:(NSData *)videoData :(int)videoSize :(int)mode :(NSString *)mediaID {

    NSURL *twitterVideo = [NSURL URLWithString:@"https://upload.twitter.com/1.1/media/upload.json"];

    // Set the parameters for the first twitter video request.
     NSDictionary *postDict;

    if (mode == 1) {

        postDict = @{@"command": @"INIT",
                     @"total_bytes" : videoSize,
                     @"media_type" : @"video/mp4"};
    }

    else if (mode == 2) {

        postDict = @{@"command": @"APPEND",
                     @"media_id" : mediaID,
                     @"segment_index" : @"0",
                     @"media" : videoData };
    }

    else if (mode == 3) {

        postDict = @{@"command": @"FINALIZE",
                     @"media_id" : mediaID };
    }

    SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:requestURL:twitterVideo parameters:postDict];

    // Set the account and begin the request.
    postRequest.account = account;
    [postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {

        if (!error) {

            if (mode == 1) {

                // Parse the returned data for the JSON string
                // which contains the media upload ID.
                NSMutableDictionary *returnedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error]
                NSString *tweetID = [NSString stringWithFormat:@"%@", [returnedData valueForKey:@"media_id_string"]];
                [self tweetVideo:videoData :result :2 :tweetID];
            }

            else if (mode == 2) {
                [self tweetVideo:videoData :result :3 :mediaID];
            }
        }

        else {
            NSLog(@"Error stage %d - %", mode, error);
        }
    }];
}

Update - Twitter API errors - https://dev.twitter.com/overview/api/response-codes

In answer to your first comment, error 503 means that the Twitter servers are overloaded and can't handle your request right now.

503 Service Unavailable The Twitter servers are up, but overloaded with requests. Try again later.

Cyanite answered 3/6, 2015 at 8:30 Comment(7)
I'm getting the status code of 503 from tweetVideoStage3 Sociable
@VNJ That basically means that the Twitter servers can't handle your request right now. You will need to try the request again. - dev.twitter.com/overview/api/response-codesCyanite
@VNJ You may have to pass an API key as well when making the request. I don't have access to my laptop right now so I can't check the code just yet. I will test this code later on today and fix it if I can.Cyanite
In tweetVideoStage2 , I'm passing following as the dictionary NSMutableDictionary *postDictionary = [[NSMutableDictionary alloc] init]; NSString *data = [videoData base64EncodedString]; [postDictionary setValue:@"APPEND" forKey:@"command"]; [postDictionary setValue:mediaID forKey:@"media_id"]; [postDictionary setValue:@"0" forKey:@"segment_index"]; [postDictionary setValue:data forKey:@"media_data"];. I dont recieve any responseSociable
@VNJ You must receive some response, even something as simple as a "200 OK". You need to parse the response data stored in "responseData" which is passed back in the request. Have a look at tweetVideoStage1 for an example of how the parse the data returned.Cyanite
Let us continue this discussion in chat.Sociable
is it possible to integrate this with the ability to add text to the tweet? or does this just post the video directly?Moreville
G
4

I know how to upload video to twitter use the new API. And I have tried it, it works.

Please check this: https://github.com/liu044100/SocialVideoHelper

You just need to call this class method.

+(void)uploadTwitterVideo:(NSData*)videoData account:(ACAccount*)account withCompletion:(dispatch_block_t)completion;

Hope it can resolve your problem.

Best Regards.

Gunderson answered 16/6, 2015 at 9:19 Comment(8)
Hello, this library looks useful. How can I insert the users tweet text and send that along with the video? It looks like this just shares the video only.Polyphony
Lizza, in the tweetVideoStage4 function,there is statusContent variable.This is Tweet text. You have to send you tweettext touploadTwitterVideo, then to tweetVideoStage2, then ...to the tweetVideoStage4 with the text. Another words create one more func parameter.Osman
@Osman thanks for pointing that out! Everything looks like it should be working, but I get all the way to the end and the stage 4 response is {"code":324,"message":"The validation of media ids failed."} . I can verify the mediaIDs I am using are all the same, and that they are coming from Twitter, it just won't take the video. Have you seen this before?Polyphony
@Lizza, to be honest didnt get this error. May be the problem with media file. try some small one 10 seconds duration with NSString *filePath = [[NSBundle mainBundle] pathForResource:@"vvideo" ofType:@"mp4"]; NSData *data = [NSData dataWithContentsOfFile:filePath options:nil error:&error]; If account is ok should work.Osman
@Polyphony {"code":324,"message":"The validation of media ids failed."} maybe the mediaID not right, please check it again.Gunderson
Looks like there was an issue with my video. Got it working now, thanks!Polyphony
Do you have a solution for swift please?Obolus
@Obolus Hello, Swift can also use SocialVideoHelperGunderson
Z
2

Been looking for sharing video on Twitter solution with below features:

  • Support chunk upload
  • Built-in support for user's credential retrieval

Since I couldn't find one meeting my need, so I decided to write one.

https://github.com/mtrung/TwitterVideoUpload

I've been testing for awhile now and it works well for me.

Hope it helps,

Regards.

Zook answered 24/12, 2015 at 5:32 Comment(0)
R
1

Try this based in @Dan answer. It not tested, but I think it can work.

Use Cocoa-pods: pod 'TwitterKit'

if you don't use Pods try with fabric

//for Extern call
//Mode is 1
//MediaId is 0
- (void)uploadTwitterVideo:(NSData*)videoData videoTitle:(NSString *)title desc:(NSString *)desc withMode:(int)mode  mediaID:(NSString *)mediaID withCompletion:(dispatch_block_t)completion
{
    NSString *twitterPostURL = @"https://upload.twitter.com/1.1/media/upload.json";

    NSDictionary *postParams;
    if (mode == 1) {
        postParams = @{@"command": @"INIT",
                       @"total_bytes" : [NSNumber numberWithInteger: videoData.length].stringValue,
                       @"media_type" : @"video/mp4"};
    } else if (mode == 2) {
        postParams = @{@"command": @"APPEND",
                       @"media_id" : mediaID,
                       @"segment_index" : @"0"};
    } else if (mode == 3) {
        postParams = @{@"command": @"FINALIZE",
                       @"media_id" : mediaID };
    } else if (mode == 4) {
        postParams = @{@"status": desc,
                       @"media_ids" : @[mediaID]};
    }

    TWTRAPIClient *twitterInstance = [[Twitter sharedInstance] APIClient];
    NSError *error;
    NSURLRequest *requestTw = [twitterInstance URLRequestWithMethod:@"POST" URL:twitterPostURL parameters:postParams error:&error];

    [twitterInstance sendTwitterRequest:requestTw completion:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        NSLog(@"HTTP Response: %li, responseData: %@", (long)response, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        if (error) {
            NSLog(@"There was an error:%@", [error localizedDescription]);
        } else {

            if (mode == 1) {
                NSMutableDictionary *returnedData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&connectionError];
                NSString *mediaIDResponse = [NSString stringWithFormat:@"%@", [returnedData valueForKey:@"media_id_string"]];
                NSLog(@"stage one success, mediaID -> %@", mediaID);
                [self uploadTwitterVideo:videoData videoTitle:title desc:desc withMode:2 mediaID:mediaIDResponse withCompletion:completion];
            } else if (mode == 2) {
                [self uploadTwitterVideo:videoData videoTitle:title desc:desc withMode:3 mediaID:mediaID withCompletion:completion];
            } else if (mode == 3) {
                [self uploadTwitterVideo:videoData videoTitle:title desc:desc withMode:4 mediaID:mediaID withCompletion:completion];
            } else if (mode == 4) {
                DispatchMainThread(^(){completion();});
            }
        }
    }];
}

This API Works as follows.

- Login when application (twitter) is installed and when is not installed

- First priority take credential from setting

Check this case

Recourse answered 4/12, 2015 at 19:46 Comment(1)
what i have to pass in "mode" and "mediaid" param?Caesarean
C
0

Swift

Its very Simple. First you need to sign in to your Twitter Account. Go to Phone Setting and click on twitter app and sign in. Now Just Call this videoUpload func anywhere

Video or Chunked uploads Method Reference

Replace your video type/extension on that code And Carefully read all twitter requirements.

var twitterAccount = ACAccount()

        func videoUpload{
                let path = Bundle.main.path(forResource: "file-Name", ofType:"mp4")

                let filePath = path
                var fileSize = UInt64()

                do {
                    //return [FileAttributeKey : Any]
                    let attr = try FileManager.default.attributesOfItem(atPath: filePath!)
                    fileSize = attr[FileAttributeKey.size] as! UInt64

                    //if you convert to NSDictionary, you can get file size old way as well.
                    let dict = attr as NSDictionary
                    fileSize = dict.fileSize()
                } catch {
                    print("Error: \(error)")
                }

                let accountStore = ACAccountStore()
                let twitterAccountType = accountStore.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)
                accountStore.requestAccessToAccounts(with: twitterAccountType, options: nil) { (granted, error) in

                    if granted {
                        let accounts = accountStore.accounts(with: twitterAccountType)
                        if (accounts?.count)! > 0 {
                            self.twitterAccount = accounts?.last as! ACAccount
                        }}}


                twitterAccount = Twitter.sharedInstance().sessionStore.session() as! ACAccount
        uploadVideoToTwitter(videoURL: URL(string : path!)! as NSURL, fileSize: UInt32(fileSize))
        }

    func uploadVideoToTwitter(videoURL:NSURL,fileSize: UInt32) {

            if let videoData = NSData(contentsOfFile: videoURL.path!){
                self.tweetVideoInit(videoData: videoData, videoSize: Int(fileSize))
            }
        }

        func tweetVideoInit(videoData:NSData,videoSize:Int) {

            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")

            var params = [String:String]()

            params["command"] = "INIT"
            params["total_bytes"]  = String(videoData.length)
            params["media_type"]  = "video/mp4"

            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)

            postRequest?.account = self.twitterAccount;

            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(error as Any)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {

                            if let tweetID = dictionary["media_id_string"] as? String{
                                self.tweetVideoApped(videoData: videoData, videoSize: videoSize, mediaId: tweetID, chunk: 0)
                            }
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }

        func tweetVideoApped(videoData:NSData,videoSize:Int ,mediaId:String,chunk:NSInteger) {

            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")

            var params = [String:String]()

            params["command"] = "APPEND"
            params["media_id"]  = mediaId
            params["segment_index"]  = String(chunk)

            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)

            postRequest?.account = self.twitterAccount
            postRequest?.addMultipartData(videoData as Data!, withName: "media", type: "video/mov", filename:"mediaFile")

            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(err)

                }else{
                    self.tweetVideoFinalize(mediaId: mediaId)
                }
            })
        }

        func tweetVideoFinalize(mediaId:String) {
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")

            var params = [String:String]()
            params["command"] = "FINALIZE"
            params["media_id"]  = mediaId

            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)

            postRequest?.account = self.twitterAccount;
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            self.postStatus(mediaId: mediaId)
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }

        func postStatus(mediaId:String) {

            let uploadURL = NSURL(string:"https://api.twitter.com/1.1/statuses/update.json")

            var params = [String:String]()
            params["status"] = "my first Video Upload"
            params["media_ids"]  = mediaId

            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)

            postRequest?.account = self.twitterAccount;

            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            print("video uploaded")
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
Conlen answered 18/9, 2017 at 20:13 Comment(0)
B
-1

I was able to upload video to twitter successfully! Below are steps referred from twitter docs:

  1. Request for twitter account

    accountStore.requestAccessToAccounts(with: twitterAccountType,options:nil){(granted, error) in
    
  2. POST media/upload (INIT)

    params["command"] = "INIT"
    params["total_bytes"]  = String(videoData.length)
    params["media_type"]  = "video/mov"
    
  3. POST media/upload (APPEND)

    params["command"] = "APPEND"
    params["media_id"]  = mediaId
    params["segment_index"]  = String(chunk)
    
  4. POST media/upload (FINALIZE)

    params["command"] = "FINALIZE"
    params["media_id"]  = mediaId
    
  5. POST media/upload

    params["status"] = twitterDescription
    params["media_ids"]  = mediaId
    

Here is twitter doc link https://dev.twitter.com/rest/media/uploading-media.html

Please fine the detailed solution for video upload to twitter using SLRequest here.

http://swiftoverflow.blogspot.in/2017/04/upload-video-to-twitter-using-slrequest.html

Buggy answered 3/4, 2017 at 9:36 Comment(1)
A link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Yogurt

© 2022 - 2024 — McMap. All rights reserved.