New with Max 6.1.7, the maxurl object gives you the ability to easily connect Max with the web using HTTP messages. If you've been thinking about creating a crowd-sourced multimedia patch or a data-driven interactive work, now is a good time to give it a shot. To demonstrate one possible direction, in this tutorial we'll look at creating a Jitter collage with Instagram photos.
If you haven't looked inside the maxurl help patch, I recommend you start there and familiarize yourself with the different tabs. There's a lot there and lots of practical examples that will give you an idea of how to use this object in a Max patch. For this tutorial, we'll be using the Javascript version of the object, XMLHttpRequest (should be familar to anyone doing Web development). The easy text manipulation in Javascript and built-in JSON parsing are a huge help for this sort of stuff.
Since we're using the Instagram API to run this, you will need to visit the Instagram developer site to get your own API client ID. If you already have an Instagram account, it's really simple. Keep the client ID handy because you'll need it later.
Setting up the XMLHttpRequest
The "bang" function in our Javascript will be used to create and send our HTTP messages. function bang() { //create a XMLHttpRequest object ajaxreq = new XMLHttpRequest(); //set the HTTP message to be sent (usually a special formatted URL) ajaxreq.open("GET",api_string); //set the callback function ajaxreq.onreadystatechange = getPictures; //send the request ajaxreq.send(); } The message that gets sent in this function is defined by the "api_string" variable. In order to have a valid request, we're going to need to set up a proper request string. By reading over the Instagram API reference, I found that we can get recent popular images by sending the string "https://api.instagram.com/v1/tags/"+tag+"/media/recent?client_id=client-id" Knowing this, we can make this simple function to grab recently popular images: function popular(){ api_string = "https://api.instagram.com/v1/media/popular?client_id="+clientID; bang(); }
Handling the Response
Back in our bang() function, we need to set up a callback function that gets triggered when the API response comes back. In our case, we are going to get a JSON object describing a collection of images. There's a lot of data that comes in there, but we are only focusing on the source URL of the images themselves. Here is what our callback function looks like: function getPictures() { payload = JSON.parse(ajaxreq.response); imageurl = new Array(); for (i=0;i < payload.data.length;i++){ imageurl[i]= payload.data[i].images.standard_resolution.url; getImageURL(i); } } In there we convert the response JSON to a Javascript object (JSON.parse), and for each image in the response we save the names of the image into an array and then call a function that downloads the image to the /media folder of the project. function getImageURL(image){ var pname = imageurl[image].replace(/^.*(\\|\/|\:)/, ''); var pp = new XMLHttpRequest(); pp.open("GET",imageurl[image]); pp._setRequestKey("filename_out",imagepath+pname); pp.onreadystatechange= filewriteCallback; pp.send(); outlet(0,pname); }
Back in the Patcher
Once we've got the image files downloaded we can just take advantage of the auto-populate feature of umenu in our Max patcher to create an easy interface to randomly load those image files in jit.qt.movie. To try a search, you'll want to go in the Max patcher and send a message to the Javascript that sets the client ID (remember that?). Once that is set, you can try sending the "popular" message to trigger the search and download process. Once that is going, you can turn on the qmetro to the right and watch the images accumulate. Try using the "offset" attrui to animate the collage.
Now that you've got the basics in place to start pulling in and using photos, try exploring the API and doing other types of image search. There are also lots of different web APIs that you can explore to connect your Max patch.
This looks impressive and I really want to check it out. When I open the project it says I'm missing "jit.*.mxo" and thus I don't see anything in the patch. Is that related to something on my end or something relating to this project?
Really into this. Thanks for sharing. Is there any possible way to tell the script to skip over duplicates? For example, if I command it to find and populate images from a certain hashtag, and then later AGAIN tell it to find and populate images from the same hashtag, it brings in the same images again as well as new ones.
@estevancarlos make sure you place the attachment files in the projects folder within your MAX folder. I had the same problem and that seemed to fix it.
@apcuddling - You could store the id's of the images that were downloaded (maybe in a Dict?), and if the API request returned those images again, you could simply throw them out. You would need some logic to request more images (I think the API provides for a startAt value, or something similar), which would be called if the results returned did not provide enough "new" images.
@nealriley Right. Yeah I noticed that they could be manually removed. But the idea I had was to set up a metro to bang the messages requesting the images. So then it would just keep fetching new images. But if I could find a way to automate the dumping of the duplicates, then I could just let it keep running and the newer images would be added in with out duplicating the old ones. Thanks for the response.
Unfortunately I think the Instagram API lacks this capability. The "automating" of this process could come from a JS function you automatically pass the results from the API call to. ie each bang would fetch new images and clean out the dupes.
@nealriley Yeah I didn't even entertain the idea that it could be done through the API. I'll toy around with some things and see what happens. I'll post back with any progress. Thanks!
Thanks! I'm afraid it's really just that simple. This error dialogue pops up saying the jit.*.mxo is "implicit." I've never heard of an object called jit.*.mxo, and my computer certainly doesn't have one. Is there supposed to be one installed?
The error message was popping up before and after I registered with Instagram developer. I'd attach some screenshots, I'm just not sure what of, outside of that error box.
@kirkpearson Not sure if this helps, But I've been messing around with the patch for the last couple of days and have noticed 2 things.
1. Make sure when you unarchived the files that they were placed in the projects folder. 2. Make sure that the Client ID for the Instagram API is getting inputted correctly.
Things seem to be working fine for me. I would like to note though, that the "jit.*.mxo" is still highlighted red in the project window. But everything is working the way what I want it to.
Found a way to prevent the patch from including duplicate images. I know it works on my Mac and it may work on windows. But it all depends on how you have your computer set up to handle files with the same name...
-Open up the inspector for the umenu that lists the names of the included images that were grabbed from Instagram and stored in the media folder. -Click on the ALL tab. -Under the FILES section, click the EDIT button next to FILE TYPES and type in ".jpg"
What happens is when you fetch for more instagram images of the same hashtag or category, they are all stored in the same folder together (the media folder). Mac OS automatically adds a number to the end of a filename if a file with same name already exists in that location. It will add a (1) or a (2) and so on. However, it adds it AFTER the file extension (.jpg). So, in turn, umenu won't include those images to be populated and used in the patch because it doesn't register them as being a .jpg file.
The duplicates will still be stored in the media folder, but umenu will just look over them when they are being populated into the patch.
Again, like I said, not sure if this will work for everybody as it could depend on how your computer or OS handles documents of the same name.
For some reason, none of the images are even downloading. There seems to be a variable problem on line 15 in the code. When tagsearch is banged, the .js window says "XMLHttpRequest is not defined, line 15." Despite the problem being so simple, I actually can't find any deficiency in the code.
@hzd I don't think you have to have a website. I have a website that I used when entering in the info, but I haven't used it in regards to the Instagram API. I just entered it so that I could continue and get the Client ID. I would imagine you could type in any random website url. But who knows. Good luck.
i was having the same problem you all were having but i fixed it. previously i had entered my client ID in the message box incorrectly with my id number inside the "<>" . when i deleted the little "<>" the patch started working. so whatever problem you're encountering probably has to do with your client id
has anybody spent much time with this yet? i would like to be able to use this to generate images with a specific hashtag and only those images. it's hard to completely understand what is actually happening onscreen. i'm sending it a "tagsearch" message and it seems to bring up all of the previous tagsearches i have made and maybe even the popular page as well? hard to tell.
i want to use this for a performance tomorrow in which i/the audience will be taking pictures/uploading to instagram during the performance. anyone present can tag their photo with the special hashtag for the evening. i'll do a "tagsearch" for that hashtag in max and project the result on a large screen, so that everyone (with a smart phone) can contribute to the visual spectacle. does that make sense?
yes, i just want to be able to make this thing generate images of only one hashtag.
When you tell the patch to grab photos from instagram (be it "popular" or a specified hashtag), it grabs them and then saves them to a file on your hard drive. When you tell the patch to "populate" the found pictures, it just loads what is in that folder. That's why you keep seeing previous pictures showing up.
Assuming you're using a mac, this folder it located in "/Applications/Max 6.1/projects/media".
Inside the media folder you will find a bunch of pictures. If you delete all of those, you can start fresh.
Knowing this also allows you to place pictures into the folder as well.
Sorry, if I'm the one asking newbie questions, but I'm not at all familiar with web stuff, like urls and OAuth or what you kids like to call it now a days :)
In web site, as I don't have a web site of my own, I could for instance use the web site of the recordcompany that I use? and "OAuth redirect_uri:"…. what is that?
As I said, I'm in way over my head with this stuff, but when I get this into Max, I can do magic :)
I have exactly the same error messages as HHELT. DVDSMOKE's suggestion doesn't apply - my ID isn't inside <>. Besides I get the first part of the error message (js: bad outlet index 1 [instagtest.js]) on opening the patch, i.e. before I even send the message with the client ID to the javascript.
OK, here's what fixed it for me. 1. In the javascript I had to delete line 10, instead calling init() from the Max patch (messagebox with "init" connected to the input of the js object). This took care of the "bad outlet index" message 2. The other problem was that I used my Instagram user ID instead of the developer client ID, duh. Should have read the explanation before diving into the patch...
@SUKANDAR KARTADINATA, thanks! For some reason, I'm still getting a "XMLHttpRequest is not defined, line 13" message inside the javascript. Do you know what's up with that?
@kirkpearson sorry, can't help much here. I didn't get this error message during my debugging. upon which message did you get it? (init, setID, or tagsearch)
@kirkpearson Please check that you have the latest version of Max installed from the DOWNLOAD page of this site. This feature was introduced in Max 6.1.7, so any previous versions won't have the ability to run this code. I look forward to seeing what you all create with this new feature. I also encourage everyone to visit the Wiki page linked in the article for future updates and other web examples, or add your own.
i've got this patch working pretty functionally, but....
eventually i get these two lines of error in the max window:
maxurl: Failed to connect to 2a03:2880:2130:9f02:face:b00c::1: No route to host instagtest.js: Javascript SyntaxError: JSON.parse, line 32
so the patch will still (mostly) work even with these errors but it will no longer "refresh" the feed. i think these errors might be coming up because i'm "refreshing" the feed too frequently, but i can't be sure. it fixes itself when i restart max. and the internet connection appears to be working fine.
hey i figured out how to allow this patch to access your personal feed. it's a little complicated so follow closely.
first: - go to http://instagram.com/developer/api-console/ - when you open this page a pop up menu should appear. - under the first part labeled USERS click "GET" next to where it says users/self/feed - before you can send this request, you need an authentication - see the "authentication" drop down menu? if you are logged in to Instagram, then one of the options when you click on it should be "instagram - authenticated user." select that. if you are not logged in, then at some point it should ask you to log in. - click the orange button that says "send" - if you have done everything correctly up to this point, then the RESPONSE section on the lower right side should come back with a message in green letters that says "OK" - keep this page open in your internet browser. we are going to come back to it.
next: - go back into your max patch - double click on the "js instaG.js" object - copy and paste the following code into there, maybe do it below the "function tagsearch" command
ok we are almost there: - the link in the code i have pasted above is abitrary and will not give you anyone's feed. i just put it there because it shows the proper syntax - you now want to go back to the api console where we made the request. - in the column labeled REQUEST, it should say GET and then a link beginning with v1/users/self, etc... - copy this link and paste it into the code on the max patch, replacing the arbitrary link i gave you - make sure the link looks right, no extraneous text or whatever, etc - now make sure to SAVE the code
THIS SHOULD BE ALL YOU NEED! now you can send the message "feed" to the "js instaG.js" object and it should work.
(This won't solve you problem but I think it may help to keep in mind when moving forward.)
I'm fairly new to jitter and still getting used to it and I could be wrong on this, but...
From what I can tell the patch AS IS will display video files but will only display a still image as the output.
I would like to mention that I did NOT have the patch load instagram videos through API.
Instead I loaded some .mov files into the media folder where the found instagram images are dropped in. Then I told the umenu to only recognize .mov files.
The patch worked as normal but only displayed the .mov files as a still image as if it were an image file.
I imagine something else will need to be changed in the patch to tell the video files to automatically play.
I'll toy around with it some more and let you know if I come across a solution.
Im really struggling to get this patch to work mainly due to my lack of knowledge of Java Script and API. Please find what I have entered in Java Script below. Please could someone point me in the right direction to link this patch to my instagram developer account?
Hello everybody. Cheers @dvdsmoke I now have set this up, so it only gets files from my instagram user account. Next thing :) How do I narrow it down to a tag in my user? So that it only shows pictures from my account with a sertain tag.
I will try to figure something out, but my javascript knowledge is comparable to a small rock :)
I have my patch set up where the [js instagtest.js] is reading outside messages being sent that designate specific script details.
I'm not all that well versed in javascript either and it did take me awhile to get the patch to finally work correctly the way I wanted...but maybe these attached screen caps will help.
Hi, How can i grab more than 20 images? And how can I grab them for a specific time? Has anyone adjusted the js file to use pagination with next_url? The instagram API has some info about pagination and if there are more than 20 images the pagination will give the next_url.
I need to download all the images for a certain hashtag from one day in March.
What is jit.*.mxo? —the path is missing in the project window. I'm getting an error in the console: instagtest.js: Javascript TypeError: payload.data is undefined, line 34
Thanks everyone for all the troubleshooting help so far - I share some issues with others here and still haven't had any success with this. I'm using MAX 7. There are the following console errors:
When I send the "tagsearch dog" message:
instagtest.js: Javascript TypeError: payload.data is undefined, line 33
When I send the "popular" message:
instagtest.js: Javascript SyntaxError: JSON.parse, line 31
to fix the payload undefined error, Instagram now wants you to put your Access_Token instead of your clientID. I created an access token with my Instagram developers account. I then added an AccessToken function to the javascript:
var AccessToken;
function AccessToken(id){ //you need a valid Instagram access_token to use this example //visit http://instagram.com/developer to get one AccessToken = id; }
and changed the tagsearch and popular strings to include the access_token instead of ClientID
Thanks Ryan, that worked. However if you only register a new app instagram, it goes in Sandbox Mode and public content is not available. You have to properly register your app with them and make a submission to go live. Other wise you can still use it but don't get access to public_content.
So if you use an access token gotten through a sandbox app, you'll get this response from any reqest you try to make:
{"pagination":{"deprecation_warning":"next_max_id and min_id are deprecated for this endpoint; use min_tag_id and max_tag_id instead"},"meta":{"code":200},"data":[]}
someone had this issue reported on stack overflow, and somebody replied with a valid access token which I'm still using... hehe
You also need to uncheck the Disable implicit OAuth in the security tab of your instagram client app if you're app client is live but still not working.
Last thing, the images url from the JSON response have a query sring at the end that looks like this : 4532622_1878004650_n.jpg?ig_cache_key=MTIxODg4OTkyNzI3NDgzNzUxNw%3D%3D.2.l
You need to get rid of it, otherwise it on save on you're desktop. cause you know.. .jpg?ig_cache... is not a file format... (at least it did not work for me on windows)...
So I changed the getImagURL function by adding a second replace to pname... you can surely use a nicer regex that does this without repetition, but I was lazy.
function getImageURL(image){
var pname = imageurl[image].replace(/^.*(\\|\/|\:)/, '').replace(/(jpg\?.*)/,"jpg");
var pp = new XMLHttpRequest();
pp.open("GET",imageurl[image]);
pp._setRequestKey("filename_out",imagepath+pname);
pp.onreadystatechange= filewriteCallback;
pp.send();
outlet(0,pname);
}
i create a new client inside http://instagram.com/developer (that is in sandbox mode, but i don't understand if is enough to run this example)
i got the access token from Instagram, and changed the js with the Ryan's indication.
but when i send the message "AccessToken", after send "setID" the .js say "no function AccessToken" even with this code inside
var AccessToken;
function AccessToken(id){ //you need a valid Instagram access_token to use this example //visit http://instagram.com/developer to get one AccessToken = id; }
and naturally when try to use tag search i got the payload error.
In my case it dosnt work too, as you can see in the image i have the message js: bad outlet index 1 [instagtest.js] I put my ID setID 9419a019d1eb45f29fe20e78be6679bd but nothing happen... Any idea to solve this?... Best!
Has anyone experienced maxurl's connection timeouts sort of blocking any future connection? After the above mentioned fixes, this patch works great for the first two hours or so, then I get a connection timeout and the only way to make it work again is to quit Max. Thoughts?