YouTube CFC Updated

This post is more than 2 years old.

I've "formally" released the new version of my YouTube CFC to it's RIAForge home. This new version doesn't have a one to one relation to the older API so I've included the old code in the zip as well. Right now it supports:

  • Various 'top' video feeds (most popular, etc)
  • Videos by category, keyword, or both
  • Videos by user
  • Comments for a video
  • Playlists for a user
  • Videos for a playlist

And of course the big one - video upload.

The major things left to do include posting new comments and updating video information. Hopefully I can get the YouTube API Blog folks to notice.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Bob posted on 4/20/2008 at 8:00 AM

Hey Ray, this is great - thank you! I was wondering if you planned to add a GetVideo function akin to the one in the CFC with the first API, so that you could grab all of the data about a specific video.

Regardless, this is really helpful - thank you!

Comment 2 by Geoff posted on 4/20/2008 at 3:40 PM

Great CFC Ray! I have a quick question about error trapping on cfhttp.

I'm always concerned about timeouts / problems connecting to third party services - how would getVideos() tell the calling app "sorry, I couldn't contact the youtube website"

Could (should?) you change getVideos() to return a struct - one key has the results recordset, and one key has a "statuscode" message maybe?

Then put a timeout on the cfhttp call, and try/catch it?

just a thought...

Comment 3 by Raymond Camden posted on 4/20/2008 at 5:42 PM

I should have more error handling, but no, I don't believe in returning structs like that. I know some folks do - but in my mind, if an error occurs, I should cfthrow. However, I like to throw my own error, using a common type and message format, so you can look for it in the code that calls my cfc.

Comment 4 by Raymond Camden posted on 4/20/2008 at 5:45 PM

@Bob - the odd thing is that what getVideo used to do is mostly contained in the get* feeds. Ie, when you get a list of videos, it contains the same info, per video, that a singular getVideo would contain. I believe. I don't believe - and I have to research this more - that you can get just ONE video based on ID. I meant to actually look into that last night but forgot. I'll make that my next priority.

Comment 5 by Bob posted on 4/20/2008 at 6:35 PM

Thanks Ray. This morning I just used CFHTTP to grab and then XMLParse() to parse the individual video XML page at http://gdata.youtube.com/fe.... It's doing the job.

Comment 6 by Raymond Camden posted on 4/21/2008 at 3:10 AM

I didn't read the whole spec, but I do remember trying to find docs for getitng one video. Where did you find that? (I'm sure it works and I'll confirm/add it later, but I'd like to be sure it is SUPPOSED to work if you know what I mean.)

Comment 7 by Bob posted on 4/21/2008 at 6:19 AM

I actually used your CFC to pull the list of videos for the user. The ID column contained the feed URL for each video, which I pulled up in Firefox and found the detailed XML. So no, I can't confirm it's SUPPOSED to work.

Comment 8 by Raymond Camden posted on 4/21/2008 at 5:28 PM

I did some more looking last night, and it does seem to be kinda documented - when you look specifically at the Entry field it does talk about the links.

So I will add this later today.

Comment 9 by jason posted on 6/24/2008 at 8:06 AM

hi, great tool, but i can't seem to make it work.

trying the test2.cfm file in the youtubeapi1 folder and keep getting "Bad, unknown, or disabled dev_id specified."

i want to test the upload function and can't get started.

the cfc is installed and i have a valid dev key.

any advice or other documentation? where to start with uploads?

thanks!

Comment 10 by Raymond Camden posted on 6/24/2008 at 11:50 AM

Don't use the youtubeapie1 folder. That's the older code. I include it for folks who may insist upon it - but in general don't support it anymore. Make sense?

Comment 11 by Louis Plante posted on 9/23/2008 at 4:03 AM

Hey Ray, excellent work on the api, i have one question though. I wanted to order the videos by the newest to the oldest. Here is the code that I'm using

<cfset yt = createObject("component", "assets.cfcs.youtube")>
<cfset pl = yt.getVideosByUser('marjenningstv')>

any suggestions?

Comment 12 by Raymond Camden posted on 9/23/2008 at 4:48 AM

My CFC returns a query. If you want to re-order it, you can use a query of query. I can investigate, later on, adding sorting.

FYI - upload is currently broken. I hope to have it fixed w/n a week. It turns out there is a bug in CF that only gets exposed with the YT api.

Comment 13 by Greg E. posted on 10/14/2008 at 2:12 AM

Hi Ray, Do you have any documentation or examples on uploading videos? This is what I have at this point and the results follow: (thanks for your help and this .cfc)

<cfinvoke component="youtube" method="init" returnvariable="yt"><cfinvokeargument name="devkey" value="#request.YouTubeDeveloperKey#"></cfinvoke>

<cfdump var="#yt.upload(video='#cffile.SERVERDIRECTORY#\#cffile.SERVERFILE#',title='Upload Test',description='Testing',categories='Education',keywords='YouTube ColdFusion')#">

Upload Result:
--------------
ErrorDetail: I/O Exception: Software caused connection abort: socket write error
Filecontent: Connection Failure
Mimetype: Unable to determine MIME type of file.
Statuscode: Connection Failure. Status code unavailable.

Comment 14 by Raymond Camden posted on 10/14/2008 at 2:17 AM

Greg - video uploads is currently broken. I have worked w/ Adobe and there IS a fix, but the fix involves a hot fix that is not yet released to the public. I'm going to bug them again about that and see when it will go public.

Long story short: You can't do the upload now- period. But you will be able to with a hotfix sometime in the (I would assume!) near future.

Comment 15 by aviva posted on 12/1/2008 at 3:29 AM

i found the hotfix:
http://kb.adobe.com/selfser...

but i get an error when trying to upload:
the error is in your cfc, trying to read an error.

can you give an example of the code needed to upload a video?

Element ERRORS.ERROR.DOMAIN.XMLTEXT is undefined in RESXML.

The error occurred in /home/mylifesp/dev_html/my-account/youtube.cfc: line 691

689 : <cfset resxml = xmlParse(result.fileContent)>
690 :
691 : <cfthrow message="YouTubeCFC Upload Error: Domain=#resxml.errors.error.domain.xmlText#, Code=#resxml.errors.error.code.xmlText#">
692 : <cfelse>

Comment 16 by Raymond Camden posted on 12/1/2008 at 3:40 AM

The only real 'doc' for upload is by reading the CFC method and looking at the arguments. Can you show me how you tried to do an upload?

Comment 17 by Derek posted on 12/22/2008 at 8:27 PM

I noticed it says you need a dev key and YT username and pwd, but in the api docs it says

Both the Client ID and Developer Key should be provided in every API request (see Using a developer key and client ID). Each application/product should have its own unique Developer Key and Client ID.
http://code.google.com/apis...

Has it changed since the last update?

Comment 18 by Raymond Camden posted on 12/22/2008 at 8:36 PM

I think ClientID is the name of the 'tool' using the service, which in this case is my tool, and is hard coded in the CFC. So basically, you don't need to worry about it.

Comment 19 by Derek posted on 12/22/2008 at 8:37 PM

ahh..ok so they aren't tied together?

Comment 20 by Raymond Camden posted on 12/22/2008 at 8:40 PM

No, it's like your cell phone. Your phone number is unique to you, but your brand name is iPhone. So my code's "brand" is, um, whatever I used (probably something with Camden in it since I'm an egotistical twit), and the dev key is what you are responsible for.

Comment 21 by Derek posted on 1/15/2009 at 7:50 PM

ok, back again. This issue is related to just retrieving videos.
Everything was working at first. Then I started getting connection failures. I did some testing and by removing the V2 param, I got it working again.

So now the past couple of days it is no longer working on the prod server which is 7,0,2,142559 , but works fine on 8 from my home dev box.

Charset [empty string]
ErrorDetail Unknown host: gdata.youtube.com: gdata.youtube.com
Filecontent Connection Failure
Header [undefined struct element]
Mimetype Unable to determine MIME type of file.
Responseheader
struct [empty]
Statuscode Connection Failure. Status code unavailable.
Text YES

here is a test page I am using
http://justs10.com/videos/t...

If anyone could help, be mucho appreciated.

Thanks,
D

Comment 22 by Raymond Camden posted on 1/15/2009 at 8:08 PM

Unfortunately this sounds like a Google/YT issue. I'm not sure what I can recommend for that. Removing the v2 param isn't a solution for me as I know I'm relying on some v2 stuff in some calls. You may want to check the network settings on production box.

Comment 23 by Lamar posted on 2/5/2009 at 1:16 AM

Ray - trying to use the upload capability but am a little clueless as to where to start. Any sample code you have for uploading?

Comment 24 by Raymond Camden posted on 2/5/2009 at 1:18 AM

Wasn't there one in the zip?

Comment 25 by Raymond Camden posted on 2/5/2009 at 1:22 AM

Here is an example, with login/key info changed:

<cfset yt = createObject("component", "youtube")>
<cfset yt.setDeveloperKey("AI39n2n17CzpcDAt6GMrXc8z6DA")>
<cfset yt.login("cfjedimaster", "password")>
<cfset r = yt.upload(expandPath('./actual.mov'),'Test/Upload Jack-O-Latern','Playing/with Jack-O-Latern youtube aug29','Music','testing fun')>
<cfoutput>id=#r#</cfoutput>

Comment 26 by tj posted on 9/3/2009 at 6:30 PM

Hi Ray - great component.

Everything is working just as it should with the exception of the upload. I used the example upload code you supplied (altered to my id, login and video location) and I'm getting the:
Element ERRORS.ERROR.DOMAIN.XMLTEXT is undefined in RESXML.

Any thoughts?

Comment 27 by tj posted on 9/3/2009 at 6:43 PM

So I just had it return resXML and it appears it does not like my DeveloperKeyID...

Comment 28 by Raymond Camden posted on 9/5/2009 at 1:44 AM

Looks like my error handling could be nicer. Did you get a new dev id though?

Comment 29 by tj posted on 9/5/2009 at 4:48 AM

Yep - working great. Great component and allows me to put off the purchase of a media encoder... for now anyways.

Thanks!

Comment 30 by Misty posted on 9/28/2009 at 11:51 AM

Ok! Very Nice Work Ray!

One last question does not it return rows more than 25 either try to fetch by category or keywords:

Just curious

Comment 31 by Raymond Camden posted on 9/28/2009 at 3:13 PM

According to the getVideosBySearch function, there is a max attribute which defaults to 25, but can go up to 50. You can paginate by using the start attribute.

Comment 32 by Shaveta posted on 9/28/2009 at 7:27 PM

Hi ray! when i try to use getplaylist, it just keeps on loading:

i am just using getplaylist, not getplaylists

is there any example to that

Comment 33 by Raymond Camden posted on 9/28/2009 at 7:28 PM

Are you saying getPlaylist() never finishes? If so, can you tell me the playlist ID you tried?

Comment 34 by Shaveta posted on 9/29/2009 at 6:36 AM

well i never did tried any ID:

i just used #yt.getplaylist#

and it keeps on loading. how can i know in youtube playlists

Comment 35 by Misty posted on 9/29/2009 at 6:42 AM

Thanks Ray! but for all functions it only returns 25, it something needs to be reworked to make it work to fetch all. and once it fetches all, pagination can be donr

Regards

Comment 36 by Raymond Camden posted on 9/29/2009 at 7:08 AM

@Shaveta: Errr - that's not how you call a method. Have you used CFCs before?

@Misty: It only returns 25 if you don't set a max attribute. You can set it to 50. Also, look at the result query. It tells you how many total items there are. With that, you can build your own pagination.

Comment 37 by Shaveta posted on 9/29/2009 at 8:02 AM

Yes! i have used CFC's Before but when i see you playlists example: first you are calling a getplaylists function with pasing yourname and then u did the recordcount and then purl=[1] so the second part is bit ambigious as to u passed it 1. will playlists be visible only for a specific user and not for all.

Comment 38 by Misty posted on 9/29/2009 at 9:55 AM

Alright:
i am fetching the gettopratedvideos, when i run it, it just returns 25 results, if u can show me a viable example here, I shall be nice. i wanna get all results and show like 1 to 10 of 3773438 results:, then i can add my pagination. currently i am bit confused as there seems to me no result query in cfc which does that stuff

Comment 39 by Raymond Camden posted on 9/29/2009 at 3:17 PM

I don't think you are listening Misty. :) Did you look at the query result? Did you see the total number of results returned? It is in the column: total. So if you have the total _possible_, and you have the ability to pass in a start argument, then you have everything you need.

Comment 40 by Raymond Camden posted on 9/29/2009 at 3:47 PM

@Shaveta: My demo code first gets all of them - this is a query. So when I then call getPlaylist, I'm simply passing in the first URL. I don't pass 1, I pass the value of the purl column, row 1. If this doesn't work for you, please share the code you used.

Comment 41 by Shaveta posted on 9/29/2009 at 4:58 PM

in this first i tried my code which apparently did not worked. then i used you example and same did a copypaste. i did returned 2 results by your names but after that it gave me error

the error i encountered is

The web site you are accessing has experienced an unexpected error.
Please contact the website administrator.

The following information is meant for the website developer for debugging purposes.
Error Occurred While Processing Request
Element ENTRY.CONTENT.XMLTEXT is undefined in ARGUMENTS.

The error occurred in C:\inetpub\wwwroot\project2\admin\com\youtube.cfc: line 392
Called from C:\inetpub\wwwroot\project2\admin\com\youtube.cfc: line 167
Called from C:\inetpub\wwwroot\project2\admin\com\youtube.cfc: line 83
Called from C:\inetpub\wwwroot\project2\playlist.cfm: line 8

390 : <cfset s.categories = categoryList>
391 : <cfset s.title = arguments.entry.title.xmlText>
392 : <cfset s.content = arguments.entry.content.xmlText>
393 : <cfset s.author = arguments.entry.author.name.xmlText>
394 : <cfset s.authorurl = entry.author.uri.xmlText>

Comment 42 by Raymond Camden posted on 9/29/2009 at 5:06 PM

Having a hard time understanding you. Did you say one of my samples failed? Or did you modify it? If it was my sample, tell me the filename. If you modified it, please email me (ray at camdenfamily dot com) the script.

Comment 43 by shaveta posted on 9/29/2009 at 5:06 PM

I noted one thing i used this and it gave me another error:

<cfset yt = createObject("component", "youtube")>
<cfset pl = yt.getPlaylists("PhilipDeFranco")>

<cfdump var="#pl#">

<cfif pl.recordCount>
<cfset plurl = pl.url[1]>
<cfdump var="#yt.getPlaylist(plurl)#">
</cfif>

Error i got

Element FEED.ENTRY is undefined in RESULT.

The error occurred in C:\inetpub\wwwroot\project2\admin\com\youtube.cfc: line 98

96 : <cfhttp url="#baseurl#" result="result">
97 : <cfset result = xmlParse(result.filecontent)>
98 : <cfif not arrayLen(result.feed.entry)>
99 : <cfreturn results>
100 : </cfif>

Comment 44 by shaveta posted on 9/29/2009 at 5:10 PM

I just coped from you demo file:

test_getplaylists.cfm and ran it but encountered above errors. if i change the users' name it shows

Element FEED.ENTRY is undefined in RESULT. error.

i have changed nothing in youtube.cfc code. i am just running it as copied from your demo folder and that's it

Comment 45 by Raymond Camden posted on 9/29/2009 at 8:39 PM

I confirmed this bug. The issue was that the playlist had no videos, and the check for that was wrong. I also found another bug as well. I've uploaded the new CFC to:

http://www.coldfusionjedi.c....

Please download and confirm. Once you do, I will update the main project.

Comment 46 by shaveta posted on 9/29/2009 at 8:43 PM

I am unable to download it

Please check the url again for download

Regards

Comment 47 by shaveta posted on 9/29/2009 at 8:44 PM

Getting this Error:

404 - File or directory not found.
The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.

Comment 48 by Raymond Camden posted on 9/29/2009 at 8:46 PM
Comment 49 by shaveta posted on 9/29/2009 at 9:11 PM

Awesome! Thanks

Comment 50 by Raymond Camden posted on 9/29/2009 at 9:14 PM

Please be sure to let me know if it works. Then I can update the official release.

Comment 51 by Misty posted on 9/30/2009 at 5:29 AM

Hi! I tried your way saying use of Max attribute but really I am lost how do i make it work to fetch all videos not only limited to 25 only. plz plz.

just let me know one example like gettopratedtags video or any other. it should all videos not only 25 please

Comment 52 by Raymond Camden posted on 9/30/2009 at 5:34 AM

Misty, I'm not going to write the entire thing for you. I gave you the basics. You have a start argument and you know the total # of results. Your code basically needs to use pagination. Here is an example that is similar: http://www.coldfusionjedi.c...

Comment 53 by Misty posted on 9/30/2009 at 6:38 AM

I successfully build up the pagination. it has been a no worry. the only issues which is making me think again & gain is that when i do like gettoprated or other it defaults to 25 only. i added the pagination showing 1 to 10 of 25. so my question is hardly it matters to paginate it returns only 25 not more.

while i am trying to get all related to that function gettoprated

Comment 54 by Raymond Camden posted on 9/30/2009 at 6:40 AM

@Misty: Um.... are you saying you have pagination working, but you want to show 50 per page, not 25?

Comment 55 by Misty posted on 9/30/2009 at 7:00 AM

When i fetch results, It shows to me only 25. I use cfdump but it restricts itself to only 25 while i am looking forward to fetch all the topratedvideos.

suppose 100 topratedvideos are listed on youtube, i ran query it just returned 25. i have added pagination but it has restricted itself to 25 only, while i want the ful youtube 100 listings as on youtube. The same is the case with all queries.

Maybe i am able to clarify what exactly my point is

Comment 56 by Raymond Camden posted on 9/30/2009 at 7:07 AM

Ah, I think I see what you mean. Only the Search API now supports max/start. My funcs for 'get so and so' do not. I'll look at adding in that as well, but no promises yet.

Comment 57 by Misty posted on 9/30/2009 at 7:46 AM

No Problem!

I am happy i am able to pinpoint my message clearly to you

Cheers

Comment 58 by Raymond Camden posted on 9/30/2009 at 5:08 PM

Please download

http://www.coldfusionjedi.c...

It contains updates to support max/start for the 'top' video type searches. Note max still has a MAX value of 100.

Comment 59 by Misty posted on 10/1/2009 at 5:20 AM

Thanks Ray! Looking forward to this to gets more support for this youtube CFC. Its an Awesome tag you have done a Great Great job.

Comment 60 by Misty posted on 10/1/2009 at 6:07 AM

I noted one thing. It shows 1 to 10 of total of 100. but it counts only to 50.

i mean API does not go beyong 50 records for every function

Comment 61 by Raymond Camden posted on 10/1/2009 at 6:08 AM

Did you try the start argument?

Comment 62 by Misty posted on 10/1/2009 at 7:12 AM

Yes Id did. i passsed it like:

getTopratedvideos("jshjsdsd",1,50)

it retur 50 recs

if try

getTopratedvideos("jshjsdsd",1,100)

it automatically comes to 25

so i have checked it does fetch more than 50, maybe issue with youtube api fetching results

Comment 63 by Raymond Camden posted on 10/1/2009 at 7:14 AM

Right, because the MAX is 50. When you set it to 100 it was too much. Keep it at 50 max.

Comment 64 by Misty posted on 10/1/2009 at 7:18 AM

am i skipping something big, you aid start argument. do i need to pass the start dynamically at the end of first 50 records and then start the next from 51st. is that so

Comment 65 by Raymond Camden posted on 10/1/2009 at 7:21 AM

When you run the query the first time, you should START with 1 and ask for 50 records. Check the TOTAL column in the query. If it is more than 50, then you need to call the CFC again, this time with 1+50, but the same max. Ie, start with 51 and get 50 rows. This will return the next 50.

Comment 66 by Misty posted on 10/1/2009 at 11:03 AM

I have this when i searched: Displaying 1 to 12 of 1000000 Records.

now if i use like this:
<cfset query = #yt.getVideosBySearch("song",1,50)#>

Element FEED is undefined in PACKET.

if i remove 1,50, it shows records but only 25. i think i have very hard time locating this that if i return total of 1000000. i can use it can get max of 50 in one shift and that shift also needs pagination to say 10 in a row.

question arises. when it reached end of the 50, how does it know to run th cfc again to get another. i think i am doing wrong

Comment 67 by Misty posted on 10/1/2009 at 11:10 AM

error, i found and removed but below the error the confusion still remains

Comment 68 by Raymond Camden posted on 10/1/2009 at 3:38 PM

The CFC doesn't do it for you. You have to do it. As I described - you check the TOTAL value (not the number of records in the column, but the TOTAL column) and if you SEE that more exist, you build links to load the next page. It is a manual process.

Comment 69 by Raymond Camden posted on 10/1/2009 at 5:14 PM

Folks, please test with the version at:

http://youtubecfc.riaforge.org

I've updated it there.

Comment 70 by Misty posted on 10/1/2009 at 10:48 PM

Thanks For pointing, it is a manual task. a thought of a solution like it should feych 10 records at a time and every next prev link, the cfc should again to fetch next 10 and do it until it reaches 100.

i am correct, but exactly i do not know how this can be done

Comment 71 by Raymond Camden posted on 10/1/2009 at 10:51 PM

Misty, I'm sorry, but I'm not going to write this code for you. I linked to an article on doing pagination above. Here is that link again:

http://www.coldfusionjedi.c...

If you google for ColdFusion and Pagination, you will see other examples. This is not a Youtube specific issue. Pagination can be done to any set of data, and there are many examples out there, not just the blog entry I linked to above.

Comment 72 by Misty posted on 10/2/2009 at 7:12 AM

Ray! i never said you write code for me of pagination, pagination is easy and i have done it. my issue comes where i told you already that run the cfc first time and fetc the first 10 records. next page, rerun the cfc and fetch the next 10 records.

i tried to make it simple by means that rather than fetching 50 first time and paginate, why not fetch 10 at a time and then paginate, but issue persists, how to fetch the next 10 after first 10.

Comment 73 by Raymond Camden posted on 10/2/2009 at 7:16 AM

Misty, I'm just at a loss. I simply cannot understand what you are asking here. It sounds like you are saying you want 2 calls to the same method to paginate automatically. Ie, first call gets 1-10, second gets 11-20. The CFC can't do that. You have to manually change the start parameter yourself.

If I'm still not reading you right... well, I hate to say I give up, but the language barrier is difficult here.

Comment 74 by Misty posted on 10/2/2009 at 7:33 AM

This time you read me right, Language barrier is a issue here but as you said, it is not possible to do like this. i cannot browse all 100 records. only first 50.

Comment 75 by Raymond Camden posted on 10/2/2009 at 7:35 AM

But you can! Unless there is a bug in the code, you just pass a start value of 51. Again, my CFC won't do this for you. You have to a) determine you have to page and b) write the code to fetch the next page.

Comment 76 by Misty posted on 10/2/2009 at 8:19 AM

Ok lets leave that point for the time being:

suppose there is a method which does not have start and max attributes, can i add to it/

Comment 77 by Misty posted on 10/2/2009 at 2:28 PM

Ok! I am not as experienced as you are but i think you cannot browse all records of youtube. like if founded are 1025. it is nearly no way i found that it can go beyond 50 records. might be you cold find a way instead

Regards

Comment 78 by Raymond Camden posted on 10/2/2009 at 3:22 PM

Misty - let me ask you this. Did you try passing a start value higher than 51? I did. It works.

Comment 79 by Misty posted on 10/2/2009 at 7:14 PM

Hmmmm! passing 51 to 100, it works but that i have to pass manually. i mean i have to tamper the file to fetch the next 50.

so i tried the start and max in the url also but still no luck as:

abc.cfm?start=1&max=10&pagenumber=2

but it did not worked either way too

Comment 80 by Raymond Camden posted on 10/2/2009 at 7:19 PM

I think you are still not getting a core concept of pagination in CF. Did you read my article? In the article, I use links that point back to the script. The starting value defaults to 1, and when I link back, I pass in a new start value. So the page basically links to itself to allow for pagination, all via URL parameters which define where to start.

I really think you need to look at the blog entry I mentioned before as it _does_ explain this concept.

Comment 81 by Misty posted on 10/2/2009 at 7:50 PM

Ok! i am using another pagination but i seems i should try yours. ok let me try with your pagingnation tool and see what i gets

Comment 82 by Misty posted on 10/2/2009 at 8:02 PM

I used Your pagination system which is quite simple to which i am using. it creates link with the start of 1 and then 11 and then 21 and it stops at 25.

how i rerun the cfc again to fetch next 25 or 50 recs,

I am going my blow my balls away with a shotgun! i am too much confused

:((

Comment 83 by Raymond Camden posted on 10/3/2009 at 6:57 AM

You rerun the code when you link to yourself. I honestly do not think you have read the article I linked to. In that article, I show how you create a link back to the current document and pass in a new START value.

_Thats_ how the CFC is run the 2nd time. The first time the user hits the page, url.start doesn't exist, so it defaults to 1, right? You determine there are more than 50 records so you build a link (again, look at the article), and now url.start is 51 and that is passed to the CFC.

Comment 84 by Misty posted on 10/3/2009 at 8:49 AM

Ok! i am doing it like this:

<cfset perpage = 10>
<cfparam name="url.start" default="1">
<cfif not isNumeric(url.start) or url.start lt 1 or url.start gt toprated.recordCount or round(url.start) neq url.start>
<cfset url.start = 1>
<cfif StructKeyExists(URL,'time')>
<cfset tr = #yt.getTopRatedVideos("#url.time#",#url.start#,50)#>
<cfelse>
<cfset tr = #yt.getTopRatedVideos("")#>
</cfif>
</cfif>

but it does seems to work, i think i am missing one big step, i am near the end but can't find the end

Comment 85 by Misty posted on 10/3/2009 at 8:57 AM

recordcount returns 25 and if parameters are used it returns 50.

now running pagination on 25 or 50 is easy and it works, how it should fetch next 50.

because pagination has toprated.recordcount which is count to every time 50 or 25, so it is possible it keeps on fetching the very next records. seems impossible to me instead

Comment 86 by Misty posted on 10/3/2009 at 10:17 AM

What i have noted, cfc cannot fetch more than 50.
That all

Comment 87 by Misty posted on 10/3/2009 at 10:42 AM

I tried this way:

http://gdata.youtube.com/fe...

it clearly indicated that it cannot go and fetch the records, max 50 allowed, so i think there is no way how it can done.

Comment 88 by Misty posted on 10/7/2009 at 8:55 PM

Hi ray! any Update on this

Comment 89 by Raymond Camden posted on 10/7/2009 at 8:58 PM

It is 50 per time. Just change it to 50. Your starting at 51, so you will get 51-101. One arg says where to start, one says how many to get. You will ALWAYS ask for 50 at a time, your just changing the starting position.

Comment 90 by ewilkinson posted on 10/18/2009 at 2:57 AM

Hi Ray. First I must say thank you for your endless contributions to the CF community. Your CFCs for youtube and amazon s3 have really saved my butt this week. In regards to the youtube CFC, I found some minor issues with the delete method. 1. 'http://gdata.youtube.com/fe... must be stripped from the videoID before it is passed to the delete method. Other methods in the CFC include this in the code. The delete method does not. 2. The first cfhttp param should be "Host" with a value of "gdata.youtube.com". Ex: "<cfhttpparam type="header" name="Host" value="gdata.youtube.com">" before the content-type param. I discovered this by reviewing the youTube API documentation here: http://code.google.com/apis...

I downloaded version 6 from RIAForge early last week, I'm wondering if I have the latest version. Thanks again for the great CFC's.
Cheers,
Eric Wilkinson

Comment 91 by Raymond Camden posted on 10/18/2009 at 6:36 PM

Thank you for the kind words, but I'm not the person behind Amazon S3 support. :)

Anyway, I took your changes as is and pushed it live. Download and check it out please.

Comment 92 by Anthony posted on 11/17/2009 at 3:14 PM

Hello Ray,

I'm trying to use the "update" function of youtube.cfc. When I do, I get a 400 / Explanatioin: Bad Request error.

Here is the code that I'm using:

<cfset yt = createObject("component", "/yt/youtube")>
<cfset yt.setDeveloperKey("mykey")>
<cfset yt.login("uname", "pword")>
<cfset r = yt.update('#form.cause_name#','#form.before_description#','Music','#cause.tags#','#cause.before_video_ytid#')>

Here are the values to the above:

form.cause_name = sample cause
form.before_description = This is a test description.
cause.tags = Online, Contribution
cause.before_video_ytid = my video id displays here...

I checked the URLs and they seem to be correct, not sure what else to try. Any help is greatly appreciated!

- Anthony

Comment 93 by Raymond Camden posted on 11/18/2009 at 4:08 AM

Google is super anal about tags. I've tried to 'massage' the tags value to make them Google happy. I don't have time to test this second - but can you run a quick test where you send one value for tags, something simple like: "Testing". No periods, commas, or spaces. Just one word - and make sure it is at least 4 characters or so long.

Comment 94 by Anthony posted on 11/18/2009 at 5:32 AM

Thanks Ray. I updated the code to generate all static simple values and I'm still getting the same error. Here is the new code:

<cfset yt = createObject("component", "/yt/youtube")>
<cfset yt.setDeveloperKey("mykey")>
<cfset yt.login("uname", "pword")>
<cfset r = yt.update('Test Name','This is a description','Music','Testing','videoidvalue')>

Comment 95 by Raymond Camden posted on 11/18/2009 at 7:27 PM

Oh shoot - you are doing an UPDATE, not an Upload. Sorry. Testing now.

Comment 96 by Raymond Camden posted on 11/18/2009 at 7:46 PM

I fixed it. Please get the latest from Subversion on RIAForge, not the zip, confirm, and then I'll release it.

Comment 97 by Anthony posted on 12/1/2009 at 6:49 AM

Hi Ray, I hope you had a great Thanksgiving! I downloaded the new upload code (youtube.cfc), tried the same code with the static values and get the same error.

Can you maybe provide me with a sample code? I may be missing something.

Thanks again!

Comment 98 by Raymond Camden posted on 12/2/2009 at 4:01 AM

Please ping me directlyu and pass along your credentials - if you feel comfortable. Obviously it works for me so I need to test exactly as you have it.

Comment 99 by Robert Whitton posted on 4/2/2010 at 2:54 AM

Hi Ray,

Thanks for being such an active and professional commentator and teacher over the years. I know I have certainly benefited from your examples and posts.

You are probably tired of talking about this CFC, but...
I am trying to use the YouTubeCFC, and like many above, can get everything working except the upload.

I think I may be missing something conceptually about the authorization process, but here is what I am trying.

I had to modify your CFC to work in openBlueDragon (ver 1.2)- basically replace all =& and also the ReMatch function in the keywords wasn't happy. For this example I am just passing a single word to avoid YT formatting issues with keywords.

<cfset yt = createObject("component", "youtube")>
<cfset yt.login("whittonr", "mypassword")>
<cfset r = yt.upload('E:\Video_Files\B\Cyprinus_carpio_Common_carp_Wide_Angle_742_S5Q5_ID~33085.m2t','Koi','Test description','Tech','Koi')>
<cfoutput>id=#r#</cfoutput>

I keep getting "YouTubeCFC Upload Error: Status: 415 / Explanation: Unsupported Media Type". I have gone and manually added the same clip to YouTube with not problem, so I do not believe that the file is bad.

The authtoken... where is that coming from? My username and password? Is that the session authorization required to then submit the uploaded file?

The DevKey - that is your specific key to go with your YouTubeCFC tool, correct? I don't need to use my Google Dev Key. correct?

Thanks in advance for your help,

Rob

Comment 100 by Raymond Camden posted on 4/3/2010 at 1:14 AM

The authtoken is made from the login. You don't need to recreate it. Basically the login command does it and stores it. It uses for the next calls.

DevKey - don't need to change it.

So - I'd like you to try something. I know that m2t may work for you on the public site, but the API may be more anal about what it requires. Try one of the more common types and see if it works ok.

Comment 101 by Robert Whitton posted on 4/7/2010 at 9:30 AM

Aloha Ray,
Sorry for the delay. I just tried both an mpg and an mp4, and had the same error: YouTubeCFC Upload Error: Status: 415 / Explanation: Unsupported Media Type.

Both uploads took several minutes before failing, as both files were large - around 50mb. I then tried a smaller mp4 - 2.7MB and received the same error.

Here is the code I am using:

<cfset filename="M.grandoculis640x480.mp4">
<cfset fileLocation = "D:\Explorers_Log\webapps\log\Temp\">
<cfset yt = createObject("component", "youtube")>
<cfset yt.login("whittonr", "mypassword")>
<cfset r = yt.upload('#fileLocation##filename#','Angelfish','Test description','Tech','Shark,Reef,Whitton')>
<cfoutput>id=#r#</cfoutput>
<cfdump var="#yt.getVideosByUser('whittonr')#" top="5">
<cfabort>

Any other ideas on things I should try to narrow down the issue?

Thanks again for your help,

Rob

Comment 102 by Raymond Camden posted on 4/8/2010 at 12:21 AM

Robert, would you feel comfortable sending me a test mp4 and your login credentials so I can recreate here? Obviously NOT in a blog comment. ;)

Comment 103 by Jason Long posted on 7/12/2010 at 5:27 PM

Hi Ray, this is a fantastic CFC. I have had it running on my dev server for the the past 5 months but last week every thing went a bit wrong.

When ever i try and upload a video im getting this error, is this anything you have seen before?

Thanks for taking the time to read this.

Jason

Element XMLATTRIBUTES.REASONCODE is undefined in a Java object of type class coldfusion.xml.XmlNodeMap referenced as ''

The error occurred in F:\sports\webroot\youtube.cfc: line 816
Called from F:\sports\webroot\youtube.cfc: line 388
Called from F:\sports\webroot\video-view.cfm: line 150
Called from F:\sports\webroot\video-view.cfm: line 138
Called from F:\sports\webroot\video-view.cfm: line 1
814 : <cfset s.videostatus = "public">
815 : <cfif structKeyExists(arguments.entry, "app:control")>
816 : <cfset s.videostatus = arguments.entry["app:control"]["yt:state"].xmlAttributes.reasonCode>
817 : </cfif>
818 :

Comment 104 by Raymond Camden posted on 7/12/2010 at 5:31 PM

It looks like maybe I made an assumption about the xml result. Add a quick cfdump to arguments.entry. Tell me what you see under app:control.

Comment 105 by Jason Long posted on 7/13/2010 at 1:39 PM

I don't seem to be able to dump it?! Despite the error the videos seem to be passing through & saving to youtube fine.

Jason

Comment 106 by Raymond Camden posted on 7/13/2010 at 3:43 PM

You need to add an abort after the dump probably.

Comment 107 by Jason Long posted on 7/13/2010 at 6:10 PM

I did need that, thanks, I am still fairly new to CF.
I am getting:

<app:control>
<app:draft>yes</app:draft>
<yt:state name='processing'/>
</app:control>

I have worked out that the problem is that once a user uploads a video I relocate them back to the video page where it displays the latest video & if it has not been processed yet then it throws up the error. I have a feeling youtube might be taking a little longer to process video than the were when I originally put the page together.

I shall check yt:state before displaying the video and get round it that way.

Comment 108 by Raymond Camden posted on 7/13/2010 at 7:13 PM

Ok - so to be clear though, this is a bug in my code though. It isn't you 'doing it too quickly'. I should update my code to NOT assume the code is there all the time. If I work on a fix, would you be willing to test it out?

Comment 109 by Jason Long posted on 7/13/2010 at 8:10 PM

yeah, there is, I have got round it rather than say using:

<cfset yt = createObject("component", "youtube")>
<cfset foo = "http://gdata.youtube.com/fe...">
<cfset z = yt.getVideo(foo)>

I have used:

<cfhttp url="http://gdata.youtube.com/fe...">
<cfif #cfhttp.Statuscode# contains '200' AND #cfhttp.Filecontent# DOES NOT CONTAIN "<yt:state name='processing'/>">
<cfset yt = createObject("component", "youtube")>
<cfset foo = "http://gdata.youtube.com/fe...">
<cfset z = yt.getVideo(foo)>
<cfdump var="#z#">
<cfelse>
#errorMSG#
</cfif>

If you do work on a fix id be more than happy to test it.

Comment 110 by Raymond Camden posted on 7/13/2010 at 10:24 PM

Please try this version: http://pastebin.com/VFVbdizL

Comment 111 by Jason Long posted on 7/14/2010 at 12:00 PM

By changing:

<cfset result = result.filecontent>
<cfif result is "Invalid id">
<cfthrow message="YouTubeCFC: Invalid id">
</cfif>
to:
<cfset statuscode = result.Statuscode>
<cfset result = result.filecontent>
<cfif result is "Invalid id" OR statuscode EQ "403 Forbidden">
<cfthrow message="YouTubeCFC: Invalid id">
</cfif>

It is now throwing up the message when I pass it the ID of a invalid/deleted/duplicate video.

Comment 112 by Raymond Camden posted on 7/15/2010 at 1:23 AM

Sorry - what block of code is that?

Comment 113 by Jason Long posted on 7/15/2010 at 11:51 AM

From line 378 in here http://pastebin.com/VFVbdizL

Comment 114 by Raymond Camden posted on 7/20/2010 at 1:32 AM

Ok, seems smart. I used

<cfhttp url="#arguments.myid#" result="result">
<cfset resulttext = result.filecontent>
<cfif resulttext is "Invalid id" OR result.statuscode EQ "403 Forbidden">
<cfthrow message="YouTubeCFC: Invalid id">
</cfif>

Comment 115 by Das Nobel posted on 8/26/2010 at 7:37 PM

Hi Raymond,
It seems like there is another bug. Please review the error below. It seems like the code is making an assumption that app:control existence will result in status attribute. If you have fixed it thats great. If you are going to explore a solution my suggestion would be to add to the conditional statement where you check for the attribute before assigning the value. I will be happy to test this for FYEGUY.com site.

Thanks for your help

Element yt:state is undefined in a Java object of type class coldfusion.xml.XmlNodeList.

The error occurred in E:\fyeguy.com\youtube2\youtubecfc\youtube.cfc: line 799
Called from E:\fyeguy.com\youtube2\youtubecfc\youtube.cfc: line 400
Called from E:\fyeguy.com\youtube2\youtubecfc\youtube.cfc: line 650
Called from E:\fyeguy.com\promotions\lolla\lookup.cfm: line 5
797 : <cfset s.videostatus = "public">
798 : <cfif structKeyExists(arguments.entry, "app:control")>
799 : <cfset s.videostatus = arguments.entry["app:control"]["yt:state"].xmlAttributes.reasonCode>
800 : </cfif>

Comment 116 by Raymond Camden posted on 8/26/2010 at 7:39 PM

I fixed this in source already. Do you have the latest from RIAForge?

Comment 117 by Das Nobel posted on 8/26/2010 at 7:55 PM

Hi Raymond,
I just saw the latest file and indeed that is what I was exploring and I can confirm that its fixed.

Thanks,
Das

Comment 118 by David posted on 4/12/2011 at 6:41 PM

This is one of the best CFCs out there. I have been using it for quite some time now (1.5 years) in production, but for some reason starting yesterday or the day before, I started getting the following error:

<b>Element SUMMARY.XMLTEXT is undefined in ENTRY.</b>

The error occurred in youtube.cfc: line 249

247 : <cfset querySetCell(results, "updated", handleDate(entry.updated.xmlText))>
248 : <cfset querySetCell(results, "title", entry.title.xmlText)>
249 : <cfset querySetCell(results, "summary", entry.summary.xmlText)>
250 : <cfset querySetCell(results, "url", entry["gd:feedLink"].xmlAttributes.href)>
251 : <cfset querySetCell(results, "videocount", entry["gd:feedLink"].xmlAttributes.countHint)>

I just finished spending about 30 minutes looking into this and can't for the life of me figure out why the entry.summary.xmlText value is not available in the output. I dumped the entire "result" and sure enough it's not there. Interestingly, neither is the videocount.

Can anyone else duplicate this? The only way I was able to get my code working again was to comment out those two lines in the CFC, which if fine for now, but I hate when things all of the sudden break (after 1.5 years of no trouble) and I can't figure out why. Any idea? Thanks.

Comment 119 by Raymond Camden posted on 4/12/2011 at 6:44 PM

My guess would be that the code should check for their existence now. Perhaps Youtube changed something in their API.

Anyway - it would be trivial to check for this. Do you have a reproducable case though so I can confirm it here? If your case involves NDA crap, you can send it to me directly and I'll delete when done.

Comment 120 by David posted on 4/12/2011 at 7:47 PM

Thanks for the quick reply! I just sent you the code by replying to the blog notification email.

Comment 121 by Raymond Camden posted on 4/12/2011 at 10:17 PM

YouTubeCFC has been updated to handle cases where summary/countHint do not exist. You can get the latest at http://youtubecfc.riaforge.org.

Comment 122 by Jeff posted on 4/28/2011 at 6:13 AM

Ray, does youtube.cfc support Browser Based Uploading.. ( http://code.google.com/apis... ). Ideally I'd like to have the user upload straight to YouTube versus the pain of uploading to my webserver and then uploading to Youtube. By the looks of things, that might not be available in this version?

Comment 123 by Raymond Camden posted on 4/28/2011 at 3:06 PM

Right, this is not available in my CFC.

Comment 124 by Jeff Mack posted on 12/10/2011 at 9:01 PM

I have been trying to figure out how to remove a video from playlist. I keep getting 400 errors. I see an authtoken in the cfc, where does that come from and is that needed to do this? I can use all the other functions just fine. Does anyone have an idea on how to this based on Rays code?

here is the link to the api info:
http://code.google.com/apis...

Comment 125 by Raymond Camden posted on 12/10/2011 at 10:30 PM

400 is coming from Google, it means the call is done wrong. I checked, and that functionality is not in my CFC. So I assumed you added it yourself? Can you share your version?

Comment 126 by Jeff Mack posted on 12/10/2011 at 11:18 PM

Thanks for responding Ray. I have been trying various different methods based on the code you have there. I guess i really don't see where the "delete" part comes in to play in their code examples. This code below was really just based on one of your other functions, i just made sure that i was passing in the playlistID and the videoID

<cffunction name="deleteFromPlaylist" access="public" returnType="any" output="false" hint="I delete a video.">
<cfargument name="playlistId" type="string" required="true">
<cfargument name="videoId" type="string" required="true">

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

<!--- Video ID may include the URL, strip it --->
<cfset arguments.videoid = replace(arguments.videoid, "http://gdata.youtube.com/fe...","")>
<cfset arguments.videoid = listFirst(arguments.videoid, "&")>

<cfset theurl &= arguments.videoId />

<cfhttp url="#theurl#" method="delete" result="result">
<cfhttpparam type="header" name="Host" value="gdata.youtube.com">
<cfhttpparam type="header" name="Content-Type" value="application/atom+xml">
<cfhttpparam type="header" name="Authorization" value="GoogleLogin auth=#variables.authtoken#">
<cfhttpparam type="header" name="X-GData-Client" value="youtubecfc">
<cfhttpparam type="header" name="X-GData-Key" value="key=#variables.devkey#">
</cfhttp>
<cfif result.responseheader.explanation is "OK">
<cfreturn "Video successfully removed.">
<cfelse>
<cfif isXml(result.filecontent)>
<cfset resxml = xmlParse(result.fileContent)>
<cfthrow message="YouTubeCFC Upload Error: Domain=#resxml.errors.error.domain.xmlText#, Code=#resxml.errors.error.code.xmlText#">
<cfelse>
<cfthrow message="YouTubeCFC Upload Error: Status: #result.responseheader.status_code# / Explanation: #result.responseheader.explanation#">
</cfif>
</cfif>
</cffunction>

Comment 127 by Jeff Mack posted on 12/10/2011 at 11:44 PM

Acutally i posted the wrong one..

<cffunction name="deleteFromPlaylist" access="public" returnType="any" output="false" hint="I delete a video from playlist.">
<cfargument name="playlistId" type="string" required="true">
<cfargument name="videoId" type="string" required="true">

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

<cfhttp url="#theurl#" method="delete" result="result">
<cfhttpparam type="header" name="Host" value="gdata.youtube.com">
<cfhttpparam type="header" name="Content-Type" value="application/atom+xml">
<cfhttpparam type="header" name="Authorization" value="GoogleLogin auth=#variables.authtoken#">
<cfhttpparam type="header" name="X-GData-Client" value="youtubecfc">
<cfhttpparam type="header" name="X-GData-Key" value="key=#variables.devkey#">
</cfhttp>

<cfreturn result>
</cffunction>

This is what i was using, the return i get with this is:

401 Token invalid

So i think has to do with the second part of my original question about the authtoken in the cfc, where would i get that?

Comment 128 by Raymond Camden posted on 12/10/2011 at 11:46 PM

The Authtoken is generated when you login. My example code should show you how you first authenticate, then you can do methods like that.

Comment 129 by Jeff Mack posted on 12/11/2011 at 12:28 AM

Ok, so i see your login and i can confirm its giving me a token. I am now back to 400 error. This is how i am calling it

<cfset yt = createObject("component", "youtube")>
<cfset yt.login("username", "password")>
<cfset dp = yt.deleteFromPlaylist('62D2AB95BFB9F362','http://gdata.youtube.com/fe...
<cfdump var="#dp#">

Comment 130 by Raymond Camden posted on 12/11/2011 at 12:31 AM

Add a debug dump, ie, <cfdump var="#result#" abort> before your cfreturn. Let's look at more of the result.

Comment 131 by Jeff Mack posted on 12/11/2011 at 12:48 AM

i think i got it, even though the ID in the playlist is the big long url which i was using, i tried just making it like the call below and that returned a good status 200, and it was removed from my list..

<cfset dp = yt.deleteFromPlaylist('62D2AB95BFB9F362','tEsesCpfljvXjvB_LBoDK-aBCrzoWfdG')>

So for anyone looking to do this, here is the function i added to the cfc.

<cffunction name="deleteFromPlaylist" access="public" returnType="any" output="false" hint="I delete a video.">
<cfargument name="playlistId" type="string" required="true">
<cfargument name="videoId" type="string" required="true">

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

<cfhttp url="#theurl#" method="delete" result="result">
<cfhttpparam type="header" name="Host" value="gdata.youtube.com">
<cfhttpparam type="header" name="Content-Type" value="application/atom+xml">
<cfhttpparam type="header" name="Authorization" value="GoogleLogin auth=#variables.authtoken#">
<cfhttpparam type="header" name="X-GData-Client" value="youtubecfc">
<cfhttpparam type="header" name="X-GData-Key" value="key=#variables.devkey#">
</cfhttp>
<cfreturn result>
</cffunction>

Ray, as always, thank you for you time and masterful knowledge. The new site template looks fantastic by the way.

Comment 132 by Terry Bankert posted on 1/14/2012 at 3:00 AM

Hey Ray was able to get addPlaylist to work by changing the function a little
<cffunction name="addPlaylist" access="public" returntype="any" output="false" hint="Adds a playlist for a user.">
<cfargument name="title" type="string" required="true">
<cfargument name="description" type="string" required="true">

<cfset var theurl = "http://gdata.youtube.com/fe...">
<cfset var result = "">
<cfset var meta = "">
<cfset var tmpFile = expandPath("./#replace(createUUID(),'-','_','all')#")>
<cfset var resxml = "">

<cfsavecontent variable="meta">
<cfoutput>
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:yt="http://gdata.youtube.com/sc...">
<title type="text">#xmlFormat(arguments.title)#</title>
<summary>#XMLFormat(arguments.description)#</summary>
</entry>
</cfoutput>
</cfsavecontent>

<cfset meta = trim(meta)>

<cfhttp url="#theurl#" method="post" result="result">
<cfhttpparam type="header" name="Host" value="gdata.youtube.com">
<cfhttpparam type="header" name="Content-Type" value="application/atom+xml">
<cfhttpparam type="header" name="Content-Length" value="#len(meta)#">
<cfhttpparam type="header" name="Authorization" value="GoogleLogin auth=#variables.authtoken#">
<cfhttpparam type="header" name="X-GData-Client" value="youtubecfc">
<cfhttpparam type="header" name="X-GData-Key" value="key=#variables.devkey#">
<cfhttpparam type="body" value="#meta#">
</cfhttp>

<cfdump var="#result#"><cfabort>
</cffunction>