YouTube API CFC

Yesterday one of my clients (roundpeg) asked for a ColdFusion interface to the YouTube API. This turned out to be rather simple since they made use of a REST API. From this work I was able to build a CFC to work with all the functions defined in the API. This lets you get video information, profile information, search for videos etc. Best of all - roundpeg, Inc was cool with me releasing the code. You can download the CFC below.

Now the bad news is that YouTube will eventually be switching to a GData based API. I am not a fan of Google's APIs so frankly I can't see this as being a good thing - but I'll worry about that when the API is updated.

Here are some sample calls:

<cfset devid = "changethis">

<cfset yt = createObject("component", "youtube").init(devid)>

<!--- get videos by user ---> <cfdump var="#yt.getVideosByUser('joerinehart')#" label="Videos by user.">

<!--- get music videos tagged Lush ---> <cfdump var="#yt.getVideosByCategoryAndTag(10,'Lush')#" label="Lush music videos." top="10">

p.s. Note that you need to get a developer profile and key before you use the code.

Download attached file.

Archived Comments

Comment 1 by Tampa ColdFusion posted on 8/22/2007 at 7:51 AM

This is downright freaky! You are reading my mind! I just googled "YouTube CFC" yesterday and didn't find much. I looked over their API and thought "hmmm, I could build one... if I ever get the time."

Thanks for saving me the time!

Comment 2 by CeeVee posted on 8/22/2007 at 6:57 PM

Really cool Ray. How would we sort the results of a keyword search by most recent upload?

Comment 3 by Raymond Camden posted on 8/22/2007 at 6:59 PM

Just use query of query on the results.

Comment 4 by CeeVee posted on 8/22/2007 at 8:02 PM

Thanks for the above response.

Another simple question... using the getVideosByTag function, how would I get the total # of records returned so I could set up "paging" links? It seems that I need to have a default perpage value. Without the total # of records returned based on my search term, I cannot create the paging links.

Comment 5 by Raymond Camden posted on 8/22/2007 at 9:09 PM

It is not currently in the API.

FYI, I have a very cool demo I'll be blogging soon. Mixes CF8+YouTube.cfc together.

Comment 6 by CeeVee posted on 8/23/2007 at 4:57 PM

I contacted YouTube API dev forum about finding the total number of records when searching by a tag. Here was their response:

"Each youtube.videos.list_by_tag response includes the
video_list.total element, which contains the total
number of records."

I can't figure out what I need to do using your CFC to view the total number of records. Am I missing something? Could you help?

Comment 7 by Raymond Camden posted on 8/23/2007 at 5:00 PM

My code doesn't support it - so it isn't anyhting you are doing wrong. I'll see if I can add this today. Most likely I will forget to post back here - so watch youtubecfc.riaforge.org for the update.

Comment 8 by CeeVee posted on 8/23/2007 at 5:10 PM

Thanks so much! I was pretty sure this was possible. I'm glad you'll be incorporating this.

BTW, either go buy Bioshock or add to your wishlist. It's amazing.

Comment 9 by Raymond Camden posted on 8/23/2007 at 5:15 PM

Bioshock is already on my wishlist - and already bought. :)

Ok the code is done. I'll be uploading to RIAForge in 5 minutes.

Comment 10 by FALCONSEYE posted on 10/16/2008 at 10:46 PM

Hey Raymond,
I am trying to use your cfc to upload videos to youtube but got some errors.
The cfhttp statement on youtube.cfc line 484 is not returning anything. When I do a cfdump, I see an empty authtoken. Could you please help?

Comment 11 by Raymond Camden posted on 10/16/2008 at 10:50 PM

Falconseye - This was discussed on another blog entry of mine, but there is a bug w/ CF7 and 8 that is blocking this feature. This HAS been fixed by Adobe and Adobe WILL be releasing a hot fix. Once they do, I'll be announcing the hot fix and uploading my latest YouTubeCFC. I was told sometime this week.

Comment 12 by FALCONSEYE posted on 10/16/2008 at 11:41 PM

Thanks Raymond. I got an authtoken back from my upload. My code is :

<cfset devid = "AI39si4J8K77YGl7yRXabWq9CFb0M-86TcuYFcYlEmnMDv4XL3OtoK7q1N4ApXYC5Y5ntbFurXGCmGi_U8mRy-CdUHezoMLIXQ">

<cfset yt = createObject("component", "youtube")>
<cfset yt.setDeveloperKey("#devid#")>

<cfset yt.login("myUserName", "myPassword")>
<cfset r = yt.upload('video.wmv','Test Upload','Playing with youtube','Music','testing,fun')>

This returns no error. When I do the following:

<cfdump var="#yt.getVideosByUser('myUserName')#" label="Videos by user.">

The cfdump returns nothing. Do you think this is still caused by the same problem?

Comment 13 by Raymond Camden posted on 10/16/2008 at 11:43 PM

No - but I'd just hold off. The new CFC updates a lot of code.

Comment 14 by Jason Brookins posted on 10/20/2008 at 8:31 PM

@Ray:

Any word on the hotfix for CF7/CF8 from Adobe?

Also, what is the best way to go about tweaking the YouTube CFC for CF7 usage?

Comment 15 by Jason Brookins posted on 10/20/2008 at 8:35 PM

Another note at the YouTube Developer Site:

"The APIs accessed by this developer ID program have been deprecated and are no longer supported. To use the new APIs or get information about migrating your applications, please visit the YouTube Developer site at code.google.com."

Does that impact YouTube CFC?

Comment 16 by Raymond Camden posted on 10/20/2008 at 8:51 PM

@Jason - 1: Not yet. I just checked. I'll give them a day or two and check again. Please feel free to remind me here.

@Jason - 2: It should be CF7 compat. The hot fix they are releasing will be for CF7 as well. If I did use any CF8 functionality, it was probably by accident and a small snippet like X++, which would need to change to x=x+1.

@Jason - 3: This was all tested with the new API.

Comment 17 by Sasha posted on 11/12/2008 at 1:50 AM

I checked the demo of this CFC, its really great. BUT, I am unable to find how you display the videos for a search query when youtube gdata returns no videos. For example : "Sizzling Model Scorch The Runway " query on youtube.com doesnt return any videos, but it returns the videos for "runway model" and so does your cfc example/demo page, but when I use your cfc files and do the same search, I do not get any videos in return. Please advice.

Comment 18 by Raymond Camden posted on 11/12/2008 at 2:12 AM

I see you emailed me directly. I responded there asking for some sample code.

Comment 19 by Anthony Escribens posted on 10/6/2009 at 5:58 AM

Hello Ray!

First of, great job on youtube.cfc !

Do you have an example on how to delete a video? I saw the function on the .cfc page and tried calling it using the following:

<cfset yt = createObject("component", "/yt/youtube")>
<cfset yt.setDeveloperKey("mydevkey")>
<cfset yt.login("myusername", "mypassword")>
<cfset r = yt.delete('#form.deleteytvideoid#')>

But it doesn't seem to be working. I'm only passing the video id as "form.deleteytvideoid". I am missing anything?

Thanks!
Anthony

Comment 20 by Anthony Escribens posted on 10/6/2009 at 6:33 AM

Hello Again Ray! :)

I found the answer to my question above.

The url had actually changed to:

<cfset var theurl = "http://gdata.youtube.com/fe...">

Now it's working!

Thanks again for a great code and everything you do for the CF Community!

- Anthony

Comment 21 by Raymond Camden posted on 10/6/2009 at 8:08 AM

Glad you got it.

Comment 22 by Anthony Escribens posted on 10/7/2009 at 4:15 PM

Ray,

When uploading a video, what does it mean when I get this error:

"YouTubeCFC Upload Error: Domain=yt:validation, Code=too_short"

Does it have to do with the number of entries into the video name or description?

Thanks,
Anthony

Comment 23 by Raymond Camden posted on 10/7/2009 at 7:33 PM

Sometimes YouTube can be a real pain about the data you sent - especially in the keywords area. Can you send me the code you used to upload? It's probably something in that area.

Comment 24 by Anthony Escribens posted on 10/8/2009 at 3:00 AM

This is the code I ran:

<cfset yt = createObject("component", "/yt/youtube")>
<cfset yt.setDeveloperKey("<key>")>
<cfset yt.login("<login>", "<password>")>
<cfset r = yt.upload('<path_to_video>','Cow Test Number 3','This is a test description for the new cause/project.','Music','Cow Test Number 3, United States, Charity, Donation, Help, ')>

- Anthony

Comment 25 by Raymond Camden posted on 10/8/2009 at 9:26 AM

Ahah. The issue is YouTube's freaky keyword parsing. You are not allowed to use a keyword with a space in it. So your "Cow Test Number 3" becomes "Cow,Test,Number,3". 3 is too short for a keyword. Just get rid of it.

Comment 26 by Anthony Escribens posted on 10/10/2009 at 2:03 AM

Yes, that did the trick. Thanks again Ray!

Comment 27 by santosh posted on 12/15/2009 at 11:09 AM

hello ray,how can we increment the no.of results more than 25.I have a problem regarding getvideosbycategoryandtag() this function is in the 2007 model of cfc.But in the new cfc it doesnot exist so i tried it in a different way.First i searched thru the tag and then filtered the results with the category the user has selected.but iam getting less results by doing filtering.By searching thru tag iam getting only 25 video results how to increament it in order to get more results after filtering also.
this is my code:
<cfset yt = createObject("component", "youtube")>
<cfset result = yt.getVideosByTag('#form.tag#')>
<!---<cfdump var="#result#">--->
<table width="100%" height="100%" border="0">
<cfoutput>
<cfset catname = "#form.cat#">
<h4>Reslts for Tag : <em>#form.tag#</em> and Category : <em>#catname#</em></h4>
<cfloop query="result" >
<cfif catname eq "#result.CATEGORIES#">
<cfset vid=listgetAt('#result.THUMBNAIL_URl#',4, '/')>
<tr><td>Title :  #result.TITLE#</td></tr>
<tr><td><a href="test_getvideo.cfm?v=#vid#" ><img src="#result.THUMBNAIL_URL#" /></a></td></tr>
</cfif>
</cfloop>
</cfoutput>
</table>

the function i used is:

<!---Changed to GDATA yotube API--->
<cffunction name="getVideosByTag" access="public" returnType="query" output="false" hint="Searches videos by tag.">
<cfargument name="tag" type="string" required="true">
<cfargument name="page" type="numeric" required="false" default="1">
<cfargument name="perpage" type="numeric" required="false" default="40">

<cfset arguments.perpage = pageFix(arguments.perpage)>
<cfreturn getVideos("#variables.rooturl#feeds/api/videos?vq=#urlEncodedFormat(arguments.tag)#&page=#arguments.page#&per_page=#arguments.perpage#")>
</cffunction>

Comment 28 by Raymond Camden posted on 12/17/2009 at 7:37 AM

I'm not quite sure I understand your issue. Did you try increasing the value used for pagesize? Also remember the YouTube's API itself puts a hard cap in - I think at 50.

Comment 29 by Misty posted on 3/22/2011 at 8:28 PM

Hi ray! I agree with Santosh! Even it shows 239090 records, but after 25 or 50 records whatever its default of showing it, it will not resturn furthur rsults!

I do not know if this is an issue with API or something else

Comment 30 by Raymond Camden posted on 3/22/2011 at 8:30 PM

So your're saying you can't get the second page of results? Again - there is a cap PER page you can't go over.

Comment 31 by Misty posted on 3/22/2011 at 11:29 PM

Well Ray!

What you exactly mean by "Cap PER Page you can't go over"?

:(

Comment 32 by Raymond Camden posted on 3/22/2011 at 11:32 PM

Google limits how many results you can get in one request. Not sure how else to say it. You may have 500 videos, but you can only get 50 at a time. Note - I'm not saying the limit is 50, I'm just giving an example. So to get videos 51-100, you would ask for the second page.

Comment 33 by Misty posted on 3/22/2011 at 11:40 PM

Yeah Pretty right, but how would i ask the api to give me next batch of records, also i was just comparing your previous youtube CFC with new Youtube CFC i found, in the new one you have removed the function

getMostLinkedVideos()

whay so! is that function is of no more usage

Comment 34 by Misty posted on 3/22/2011 at 11:40 PM

Yeah Pretty right, but how would i ask the api to give me next batch of records, also i was just comparing your previous youtube CFC with new Youtube CFC i found, in the new one you have removed the function

getMostLinkedVideos()

whay so! is that function is of no more usage

Comment 35 by Raymond Camden posted on 3/22/2011 at 11:45 PM

First off, which API are you using. I did not build in support for paging in all of them. I did for getVideosBySearch though. In it there is an attribute "start" that defines what value you start with. So you would use that to get the next page of items.

As for getMostLinkedVideos - it may have been removed by YouTube's API. If it still exists I could add it back end.

Comment 36 by Misty posted on 3/22/2011 at 11:49 PM

Yes! i am taking about the search page, not about anything else!

because search can return me 500+ records, so your say i fetched 50 records and displayed on a page,

then i clicked again next and it again ran the query and fetched next records, but what parameters i pass so it start from next onwards, any IDEA

Comment 37 by Raymond Camden posted on 3/22/2011 at 11:50 PM

I just told you. The CFC method takes an argument, Start, that defines where to start. So if you got 50 back and see that 500+ exist, you call the CFC again and ensure you pass start=51.

Comment 38 by Misty posted on 3/22/2011 at 11:53 PM

hmm! Will try it out & check if it works or not, will post later

Comment 39 by Misty posted on 3/23/2011 at 8:27 AM

Well! ray, i could find a way to do it!

I hope you might have some IDEA which you would like to share

if not then this cannot be an easy way out

Comment 40 by Raymond Camden posted on 3/23/2011 at 2:49 PM

I'm confused. Did you use the start argument? It should just plain work.

Comment 41 by Misty posted on 3/24/2011 at 10:38 AM

i used but i have no idea how it will work

Comment 42 by Raymond Camden posted on 3/24/2011 at 3:14 PM

Misty, I'm sorry, but I do not know what to tell you. I've said multiple times now how the argument works. Do you know how to call methods in ColdFusion and pass arguments at all? If not - it may make sense to review some of the basic documentation.

Can you show me how you are calling my CFC with the start parameter?

Comment 43 by Misty posted on 3/25/2011 at 12:06 AM

yep! I know what u are taking about and i know how to call/pass arguments!

here what i am doing!

<cfif IsDefined('url.showNext') AND url.showNext IS NOT 0>
<cfset mostRecent = #yt.getRecentlyFeaturedVideos(#url.showNext#,#url.showNext#)#>
<cfelse>
<cfset mostRecent = #yt.getRecentlyFeaturedVideos()#>
</cfif>

at the end i am just doing a recordcount so it should count the records on page and then add the nbext 50 or 25 in it, i might be wrong the way i am doing, but that is all what i found!

Comment 44 by Raymond Camden posted on 3/25/2011 at 12:07 AM

And url.shownext is 50? Or some other number?

Comment 45 by Misty posted on 3/25/2011 at 8:16 AM

it is a number, on first page, it will show 25 as ur api says 25 is default maximum is 50, so recount comes to 25 and then again it queries the cfc to start from 25 onwarsd ro next 25 but i am not sure it is working fine or not!

i tested it a bit was not working as i expected,

Comment 46 by Raymond Camden posted on 3/25/2011 at 6:23 PM

I'm having a hard time parsing your last comment. Are you saying you passed 25,25 (ie, start at 25 and show 25), and the results were the exact same? That would mean paging is broken. You said you weren't sure - so please double check.

Comment 47 by Raymond Camden posted on 3/25/2011 at 6:26 PM

I just ran a test:

<cfset vids = yt.getRecentlyFeaturedVideos()>
<cfdump var="#vids#">
<cfset vids = yt.getRecentlyFeaturedVideos(25)>
<cfdump var="#vids#">

and the second dump shows results 25-50. It's working. I'm not sure what else to tell you.

Comment 48 by Jacob posted on 4/7/2011 at 10:10 PM

Hi, I have made a test online and local and in both I receive this error "An error occured while Parsing an XML document.
Premature end of file"

Comment 49 by Raymond Camden posted on 4/8/2011 at 5:29 PM

Interesting. Can you debug the CFC a bit log the response from the http call?

Comment 50 by Mark posted on 11/22/2012 at 4:38 AM

Just tried it running CF9:

An error occured while Parsing an XML document.
Premature end of file.

The error occurred in C:\web\freetabs\youtube\youtube.cfc: line 60

58 :
59 : <cfhttp url="#variables.rooturl#youtube.users.get_profile&user=#urlEncodedFormat(arguments.user)#" result="result">
60 : <cfset xresult = xmlParse(result.fileContent)>
61 :
62 : <cfif structKeyExists(xresult.ut_response, "error")>

Any ideas?

Comment 51 by Mark posted on 11/22/2012 at 4:50 AM

Really all I am hoping to do is to check YouTube to see if a video still exists. I have a database with YouTube codes, but don't want to render the embedd code if the video is no longer online. So some sort of call like your example #yt.getVideo('3rz5L0LYRqI')#" . Not sure how to do this? Maybe <cfif #yt.getVideo('3rz5L0LYRqI')# IS NOT "">?
Can't really experiment as I am getting the error as noted in the above comment.

Comment 52 by Raymond Camden posted on 11/22/2012 at 7:02 AM

1) Try to cfdump result and see what it is.

2) So yes, getVideo should throw an error for an invalid/non-existent ID. It should.

Although - does your problem with 1 go away if you use a video ID you _know_ is good?

Comment 53 by Mark posted on 11/25/2012 at 12:30 AM

Can't get past the: "An error occured while Parsing an XML document. Premature end of file. " regardless of whether it's a valid YouTube video or not. Guess I've have to seek out a different way to do this.

Comment 54 by Raymond Camden posted on 11/25/2012 at 1:40 AM

Don't give up. Did you see where I said to cfdump? That will tell you what was returned and will help explain why the xmlParse is failing.