38

I want my app to be able to upload videos to instagram.

Instagram IPhone Hooks gives information how to use the iphone hooks to upload a photo to instagram. My question is if anyone has any experience on how to accomplish the same but for a video?

Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
Nilsymbol
  • 515
  • 1
  • 9
  • 25
  • 1
    From developers support page: "Make sure to tag your questions with the Instagram tag to get fast answers from other fellow developers and members of the Instagram team". It would be nice, if instagram team answered this question! – vokilam Feb 20 '14 at 14:13
  • 1
    iOS app Cinamatic is doing Instagram video POST, apparently using HTTP POST and Instagram oAuth – loretoparisi Sep 15 '14 at 21:26

9 Answers9

44

Instagram's API doesn't directly support uploading anything from 3rd party applications. Therefore you have to do some ugly user experience compromises when providing the functionality to your users.

First, Prepare the video you want to upload to Instagram and store the path to it somewhere

Second, Save it to the user's Camera Roll:

if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(filePath)) {
    UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}

Third, now that the video is saved, tell the user that in order to upload the video to their Instagram, they must select it from their camera roll after clicking the upload button.

The upload button would simply do the following:

NSURL *instagramURL = [NSURL URLWithString:@"instagram://camera"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
    [[UIApplication sharedApplication] openURL:instagramURL];
}

It's very silly that the Instagram API doesn't support immediate media selection through any of the API endpoints for upload purposes, but as it stands right now, this is the only way.

Nico
  • 1,336
  • 10
  • 13
  • 16
    While the publicly available documentation makes no mention of it, there is indeed a way of launching Instagram with a photo or video preselected and ready to be edited. Long story short you can do something like this `instagram://library?AssetPath=[CAMERA ROLL URL]&InstagramCaption=[MESSAGE]` where the both arguments must be url encoded. I describe the [whole process in our blog here](http://blog.horizon.camera/post/102273431070/video-share-objc-ios-instagram). – Stelabouras Dec 15 '14 at 17:55
  • 1
    It seems that currently it is working only when Instagram was terminated and is loaded freshly. If Instagram is already running the previous video will be selected. In some cases when cloud is enabled you won't see the video at all. It might be a problem/change in the latest Instagram release. Hyperlaps also experience the same behaviour. – Pichirichi Jun 01 '15 at 08:04
  • @Stelabouras : I'm unable to load the selected Video in Instagram Image/Video Uploader page – Vaibhav Jhaveri Jun 01 '15 at 10:12
  • 1
    Note that in iOS 9 you'll need to whitelist the Instagram scheme. See this SO answer: http://stackoverflow.com/questions/30987986/ios-9-not-opening-instagram-app-with-url-scheme – Stan James Nov 06 '15 at 01:23
  • error http://stackoverflow.com/questions/34226433/instagram-hooks-pre-select-media-issue – jose920405 Dec 23 '15 at 17:25
21

I had a similar question: Instagram Video iPhone Hook and I figured it out. There is an undocumented iPhone hook that allows you to automatically select assets from the iPhones photo roll, and preload a caption for the video. This should give you the same user experience that Flipagrams app has with sharing a video to Instagram.

instagram://library?AssetPath=assets-library%3A%2F%2Fasset%2Fasset.mp4%3Fid%3D8864C466-A45C-4C48-B76F-E3C421711E9D%26ext%3Dmp4&InstagramCaption=Some%20Preloaded%20Caption

NSURL *videoFilePath = ...; // Your local path to the video
NSString *caption = @"Some Preloaded Caption";
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:[NSURL URLWithString:videoFilePath] completionBlock:^(NSURL *assetURL, NSError *error) {
    NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:@"instagram://library?AssetPath=%@&InstagramCaption=%@",[assetURL absoluteString].percentEscape,caption.percentEscape]];
    if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
        [[UIApplication sharedApplication] openURL:instagramURL];
    }
}];
Dharmesh Dhorajiya
  • 3,976
  • 9
  • 30
  • 39
johnnyg17
  • 610
  • 6
  • 14
  • Quick Note: seems like it is necessary to delay the opening of the URL of newly saved assets for a few seconds. otherwise the second to last video is the one selected. – johnnyg17 Oct 15 '14 at 00:01
  • Brilliant, precisely what I was looking for. Works like a charm. Now I just need to find the equivalent hook for Vine. Any insights? – BenW Oct 25 '14 at 09:10
  • I could not find anything. Do you know of any apps that do hooks to vine? – johnnyg17 Oct 27 '14 at 20:36
  • Flipagram posts to Vine directly without hooks, but they must be using a private API. I also looked into whether I could programmatically simulate a click on the Vine button inside the UIDocumentInteractionController popup view, or else restrict the view to show just Vine, but no luck yet. (The Vine icon is nested about 9 levels deep inside the UI hierarchy, but it's just a UIImageView, not a UIButton.) – BenW Oct 28 '14 at 01:51
  • Did you see this? http://stackoverflow.com/questions/19888024/how-to-upload-video-to-vine-programmatically-on-ios – johnnyg17 Oct 28 '14 at 05:22
  • I saw that, but I'd rather find a way to send the video to the Vine app for cropping/adjusting/uploading, rather than deal with all the authentication/posting/UI within my own app. I just wish UIDocumentInteractionController had an API that let you query for a given app and jump directly there without popping up the UI. – BenW Oct 28 '14 at 20:55
  • there is a issue. I have to open video from logs. and i am saving the asset-url to database. But it always opening the first video. Why? any idea – Sourabh Sharma Mar 20 '15 at 11:42
  • Not able to get proper asset becuase using above code, i'm able to switch to Instagram App but unable to open image/video uploader page with selected Video – Vaibhav Jhaveri Jun 01 '15 at 10:09
  • @VNJ Seems like Instagram may have updated their code for using this hook. Possibly something to do with iOS 8 updating the way it handles assets. If I find a solution, I will update my answer. – johnnyg17 Jun 01 '15 at 16:00
  • @VNJ Are you creating a new video or are you using an existing video? – johnnyg17 Jun 01 '15 at 16:15
  • Using existing video, present in Photo Library – Vaibhav Jhaveri Jun 01 '15 at 16:23
  • @VNJ Seems like Pichirichi is right. There seems to be a bug where if the Instagram app is already open and does not already have your asset already loaded, it will select the wrong media. However, if you are using a asset that is already loaded in the Instagram app, it should be selected. I would imagine Instagram will fix this since Hyperlapse uses the same method of opening the media. – johnnyg17 Jun 01 '15 at 16:28
  • Actually, I'm loading video from my App and then I want to send this selected video to Instagram – Vaibhav Jhaveri Jun 01 '15 at 16:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/79383/discussion-between-vnj-and-johnnyg17). – Vaibhav Jhaveri Jun 02 '15 at 06:15
  • error http://stackoverflow.com/questions/34226433/instagram-hooks-pre-select-media-issue – jose920405 Dec 23 '15 at 17:22
10

try with:

instagram://library?AssetPath=yourVideoPath

i found the solution here: http://blog.horizon.camera/post/102273431070/video-share-objc-ios-instagram

user1755548
  • 101
  • 1
  • 2
  • Works but no pre-select media http://stackoverflow.com/questions/34226433/instagram-hooks-pre-select-media-issue – jose920405 Dec 23 '15 at 17:23
5

Updated for iOS 9.

First, for iOS9 you'll need to add to your Info.plist file. Add a key a LSApplicationQueriesSchemes with the value instagram. This will whitelist the Instagram scheme. More info here.

Here is working code based on johnnyg17's:

NSString *moviePath = @"<# /path/to/movie #>";
NSString *caption = @"<# Your caption #>";
NSURL *movieURL = [NSURL fileURLWithPath:moviePath isDirectory:NO];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:movieURL
                            completionBlock:^(NSURL *assetURL, NSError *error)
{
    NSURL *instagramURL = [NSURL URLWithString:
                           [NSString stringWithFormat:@"instagram://library?AssetPath=%@&InstagramCaption=%@",
                            [[assetURL absoluteString] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]],
                            [caption stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]]
                           ];
    if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
        [[UIApplication sharedApplication] openURL:instagramURL];
    }
    else {
        NSLog(@"Can't open Instagram");
    }
}];

A sample instagramURL would be:

instagram://library?AssetPath=assets%2Dlibrary%3A%2F%2Fasset%2Fasset%2Emov%3Fid%3D69920271%2D2D44%2D4A84%2DA373%2D13602E8910B6%26ext%3Dmov&InstagramCaption=Super%20Selfie%20Dance%20%F0%9F%98%83

Update 2016/5: Note that ALAssetsLibrary is now deprecated for saving to users photo album, and the Photos Framework is now reccomended.

Community
  • 1
  • 1
Stan James
  • 2,535
  • 1
  • 28
  • 35
  • I'm using this but you can help me with this? http://stackoverflow.com/questions/34226433/instagram-hooks-pre-select-media-issue – jose920405 Dec 11 '15 at 15:19
  • @jose920405 I'll take a look. BTW, if my answer helped. Please give it an upvote so others can find it. – Stan James Dec 12 '15 at 04:53
  • Thanks crash issue solved, now I am allowing only [NSCharacterSet alphanumericCharacterSet] done the trick. Now I am able to open Instagram app. and upload video to. – Arpit B Parekh Jul 31 '17 at 06:18
2

Here is swift code for share video on Instagram.

here videoURL is asset url of video.

 func shareVideoToInstagram()
    {
        let videoURL : NSURL = "URL of video"

        let library = ALAssetsLibrary()
        library.writeVideoAtPathToSavedPhotosAlbum(videoURL) { (newURL, error) in

            let caption = "write your caption here..."

            let instagramString = "instagram://library?AssetPath=\((newURL.absoluteString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()))!)&InstagramCaption=\((caption.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()))!)"

            let instagramURL = NSURL(string: instagramString)

            if UIApplication.sharedApplication().canOpenURL(instagramURL!)
            {
                UIApplication.sharedApplication().openURL(instagramURL!)
            }
            else
            {
                print("Instagram app not installed.")
            }                
        }
    }

Make sure that you have added below code in info.plist:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>instagram</string>
</array>
Adnan T.
  • 1,166
  • 1
  • 8
  • 8
2

Instagram has updated this to use the newer Photos Library. Now, instead of passing the image/videos URL, you can simply pass the corresponding PHAsset's localIdentifier:

PHAsset *first = /* Some PHAsset that you want to open Instagram to */;

NSURL *instagramURL = [NSURL URLWithString:[@"instagram://library?AssetPath=" stringByAppendingString:first.localIdentifier]];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
    [[UIApplication sharedApplication] openURL:instagramURL];
}
Tim
  • 875
  • 10
  • 15
1

The Instagram API is extremely limited in its upload functionality, particularly when it comes to video files.

From what I understand, you basically have two options when it comes to uploading media to Instagram. You can either use the Document Interaction API to pass an image over to the Instagram app, or you can call up the Instagram camera and ask the user to choose from their camera roll (as Nico said).

I'm pretty sure you can only pass JPEG or PNG files to Instagram through the Document Interaction system, so for video I believe you're stuck with the camera roll for now. It's definitely not ideal - the app I'm working on right now uses iPhone hooks, but we've decided to stick with images until Instagram improves their API.

Community
  • 1
  • 1
David Schwartz
  • 507
  • 3
  • 14
0

I have used below code and it's working for me.

` [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            switch (status) {

                case PHAuthorizationStatusAuthorized: {

                    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"instagram://"]])
                    {
                            [MMProgressHUD setPresentationStyle:MMProgressHUDPresentationStyleExpand];
                            [MMProgressHUD showWithTitle:APPNAME status:@"Please wait..."];

                            _FinalVideoPath = [_FinalVideoPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];

                            NSURL *videoUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@", _FinalVideoPath]];

                            dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
                            dispatch_async(q, ^{

                                NSData *videoData = [NSData dataWithContentsOfURL:videoUrl];

                                dispatch_async(dispatch_get_main_queue(), ^{

                                    // Write it to cache directory
                                    NSString *videoPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"file.mov"];

                                    [videoData writeToFile:videoPath atomically:YES];

                                    [self createAlbumInPhotosLibrary:APPNAME videoAtFile:[NSURL fileURLWithPath:videoPath]ShareOnString:@"Instagram"];

                                });
                            });

                    }
                    else
                    {

                        [MMProgressHUD dismiss];

                        [STMethod showAlert:self Title:APPNAME Message:@"Please install Instagram to share this video" ButtonTitle:@"Ok"];
                    }

                    break;
                }

                case PHAuthorizationStatusRestricted: {
                    [self PhotosDenied];
                    break;
                }
                case PHAuthorizationStatusDenied: {

                    [self PhotosDenied];
                    break;
                }
                default:
                {
                    break;
                }
            }
        }];

- (void)createAlbumInPhotosLibrary:(NSString *)photoAlbumName videoAtFile:(NSURL *)videoURL ShareOnString:(NSString*)ShareOnStr
{

    // RELIVIT_moments
    __block PHFetchResult *photosAsset;
    __block PHAssetCollection *collection;
    __block PHObjectPlaceholder *placeholder;

    // Find the album
    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", photoAlbumName];
    collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
                                                          subtype:PHAssetCollectionSubtypeAny
                                                          options:fetchOptions].firstObject;
    // Create the album
    if (!collection)
    {
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:photoAlbumName];
            placeholder = [createAlbum placeholderForCreatedAssetCollection];

        } completionHandler:^(BOOL success, NSError *error) {

            if (success)
            {
                PHFetchResult *collectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[placeholder.localIdentifier]
                                                                                                            options:nil];
                collection = collectionFetchResult.firstObject;

                [self saveVideoInRelivitFolderSetPlaceHolder:placeholder photosAsset:photosAsset collection:collection VideoAtFile:videoURL ShareOnStr:ShareOnStr];

            }
            else
            {
                [MMProgressHUD dismiss];
            }

        }];

    } else {

        [self saveVideoInRelivitFolderSetPlaceHolder:placeholder photosAsset:photosAsset collection:collection VideoAtFile:videoURL ShareOnStr:ShareOnStr];
    }

}


- (void)saveVideoInRelivitFolderSetPlaceHolder:(PHObjectPlaceholder *)placeholderLocal photosAsset:(PHFetchResult *)photosAssetLocal  collection:(PHAssetCollection *)collectionLocal VideoAtFile:(NSURL *)videoURL ShareOnStr:(NSString*)ShareOnstring
{

    __block PHFetchResult *photosAsset = photosAssetLocal;
    __block PHAssetCollection *collection = collectionLocal;
    __block PHObjectPlaceholder *placeholder = placeholderLocal;

    // Save to the album
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:videoURL];
        placeholder = [assetRequest placeholderForCreatedAsset];
        photosAsset = [PHAsset fetchAssetsInAssetCollection:collection options:nil];

        PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection
                                                                                                                      assets:photosAsset];
        [albumChangeRequest addAssets:@[placeholder]];

    } completionHandler:^(BOOL success, NSError *error) {
        if (success)
        {
            NSLog(@"done");

            NSString *LocalIdentifire=placeholder.localIdentifier;

            NSString *AssetIdentifire=[LocalIdentifire stringByReplacingOccurrencesOfString:@"/.*" withString:@""];

            NSString *Extension=@"mov";

            NSString *AssetURL=[NSString stringWithFormat:@"assets-library://asset/asset.%@?id=%@&ext=%@",Extension,AssetIdentifire,Extension];

            NSURL *aSSurl=[NSURL URLWithString:AssetURL];

            [MMProgressHUD dismiss];

            if ([ShareOnstring isEqualToString:@"Instagram"])
            {
                NSLog(@"%@",AssetURL);

                NSString *caption = @"#Zoetrope";

                NSURL *instagramURL = [NSURL URLWithString:
                                       [NSString stringWithFormat:@"instagram://library?AssetPath=%@&InstagramCaption=%@",
                                        [[aSSurl absoluteString] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]],
                                        [caption stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]]
                                       ];

                if ([[UIApplication sharedApplication] canOpenURL:instagramURL])
                {
                    [MMProgressHUD dismiss];
                    [[UIApplication sharedApplication] openURL:instagramURL];
                }
                else
                {
                    NSLog(@"Can't open Instagram");
                    [MMProgressHUD dismiss];

                    [STMethod showAlert:self Title:APPNAME Message:@"Please install Instagram to share this video" ButtonTitle:@"Ok"];
                }

            }
             else
            {
                NSString *videoPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"file.mov"];

                NSError *removeError = nil;

                [[NSFileManager defaultManager] removeItemAtURL:[NSURL fileURLWithPath:videoPath] error:&removeError];

                NSLog(@"%@",[removeError localizedDescription]);

                ZShareSuccessViewController *ShareView=[self.storyboard instantiateViewControllerWithIdentifier:@"ZShareSuccessViewController"];

                [self.navigationController pushViewController:ShareView animated:true];

            }
        }
        else
        {

            if (![ShareOnstring isEqualToString:@"Instagram"] || [ShareOnstring isEqualToString:@"facebook"])
            {
                [self PhotosDenied];
            }

            [MMProgressHUD dismiss];

            NSLog(@"%@", error.localizedDescription);
        }
    }];

}


`
-3

you can done by media end point

https://api.instagram.com/v1/media/3?access_token=ACCESS-TOKEN

Get information about a media object. The returned type key will allow you to differentiate between image and video media.

http://instagram.com/developer/endpoints/media/

Here this link is for get image media id. but i hope same technique will have help in video.

Where do I find the Instagram media ID of a image

NSURL *instagramURL = [NSURL URLWithString:@"instagram://media?id=315"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
    [[UIApplication sharedApplication] openURL:instagramURL];
}

Advantage info:

  1. instagram://camera will open the camera or photo library (depending on device),
  2. instagram://app will open the app
  3. instagram://user?username=foo will open that username
  4. instagram://location?id=1 will open that location
  5. instagram://media?id=315 will open that media
Community
  • 1
  • 1
codercat
  • 22,873
  • 9
  • 61
  • 85