Message Boards Message Boards

GROUPS:

Playing with YouTube from Mathematica

Posted 2 months ago
788 Views
|
6 Replies
|
10 Total Likes
|

Originally here (the embedded iframes actually work there)


Playing with YouTube from Mathematica

Today I'm gonna quickly show off something I made for a friend (and about which I'd been thinking for some time). We're gonna use the YouTube API in Mathematica to do a have some fun (but not too much fun, mind you!).

Installing the YouTube Connection

My connection to the YouTube API is built on Mathematica's ServiceConnect framework. I've talked about these before in many different contexts but today we'll just use it. To install we pull the paclet off my server :

PacletInstall["ServiceConnection_YouTube",
  "Site"->
    "http://www.wolframcloud.com/objects/b3m2a1.paclets/PacletServer/"
  ]

(*Out:*)

post22-8529256040837869960

Authenticating with YouTube

One installed, we connect to the service as usual:

$so = ServiceConnect["YouTube"]

This will open a dialog:

post22-2534758878895670558

We'll click the sign in button, pick and account (I'll use my new personal account steve.wolfraum@gmail.com ):

post22-6891487155877384696

When we click "Allow" either we'll be taken to a nicely formatted local page with an access code running via HTTPHandling`StartWebServer or if that's being glitchy as it was right now, we'll copy the part of the URL starting with "code=4/..." :

post22-5755985516881850876

Finally, we're connected:

(*Out:*)

post22-6049558537553480280

Getting Data

The majority of the currently supported methods have to do with getting data about YouTube:

$so["Requests"]

(*Out:*)

{"Authentication","DeleteVideo","ID","Information","LastRequest","ListCaptions","ListChannelActivity","ListChannels","ListChannelSections","ListComments","ListCommentThreads","ListPlaylistItems","ListPlaylists","ListSubscriptions","ListVideos","Name","RawRequests","RequestData","RequestParameters","Search","UpdateVideo","UploadVideo","VideoURL"}

We'll start with a search, maybe. First let's see what parameters we have to work with:

$so["RequestParameters", "Request"->"Search"]

(*Out:*)

<|"Parameters"->{"q","part","forContentOwner","forDeveloper","forMine","relatedToVideoId","channelId","channelType","eventType","location","locationRadius","maxResults","onBehalfOfContentOwner","order","pageToken","publishedAfter","publishedBefore","q","regionCode","relevanceLanguage","safeSearch","topicId","type","videoCaption","videoCategoryId","videoDefinition","videoDimension","videoDuration","videoEmbeddable","videoLicense","videoSyndicated","videoType"},"Required"->{"part"}|>

Then we'll search for something bland, like "Steve Wolfraum". The YouTube API requires this "part" parameter to know what to return to use. I like to get the "id" and "snippet" parts, but you can pick for yourself which parts you want. Just comma-separate your values and you can get multiple different ones:

mySearch = $so["Search", "q"->"Steve Wolfraum", "part"->"id,snippet"]

(*Out:*)

post22-4316213154658629458

We see there are tons of results for "my" name but we only get them five at a time. We can use the "nextPageToken" to get the next page of results, though. We can bump up the number we get with the "maxResults" parameter, but I see no need for that right now. Let's look at the first result here. I'll drill straight into that snippet parameter, as that's the most interesting part:

mySearch["items", 1, "snippet"]

(*Out:*)

post22-498969337448306280

And we see, sadly, that instead of getting results for my name, Steve Wolfraum, we get them for some random dude name Stephen Wolfram. Not to be deterred, let's at least get something out of this and see a thumbnail for all our results. Tragically, we can't download videos with the YouTube API, but at least we get thumbnails...hooray? To make things more fun, we'll also add a filter to all these results, as the raw thumbnails really aren't all that interesting.

ImageAdjust@LaplacianGaussianFilter[Import[#], 3]&/@
  Normal@mySearch["items", All, "snippet", "thumbnails", "high", "url"]

(*Out:*)

post22-8416895123856568403

Cool. There's some data. We can also pull out statistics and things, say for different videos broadcast on the Wolfram Research channel. First we'll get their channel ID:

wriChannel=
  $so["Search", "q"->"Wolfram Research", "type"->"channel",
    "part"->"id", "maxResults"->"1"]["items", 1, "id", "channelId"]

(*Out:*)

"UCJekgf6k62CQHdENWf2NgAQ"

Now we'll use this to extract the 50 most popular videos:

wriVids=$so["Search", "channelId"->wriChannel, "type"->"video", 
  "order"->"viewCount", "part"->"id,snippet", "maxResults"->"50"]

(*Out:*)

post22-5403531027782801587

And now we'll get view counts:

wriStats=$so["ListVideos", 
  "id"->StringRiffle[Normal@wriVids["items", All, "id", "videoId"], ","], 
  "part"->"statistics"
  ]

(*Out:*)

post22-4181911101890639189

And then we'll make a WordCloud of titles vs viewcounts:

WordCloud@
  AssociationThread[
    Normal@wriVids["items", All, "snippet", "title"],
    ToExpression@Normal@wriStats["items", All, "statistics", "viewCount"]
    ]

(*Out:*)

post22-948349109694102953

And we see as far as YouTube cares, there's really only one video WRI has made. But dropping that one we might see some more interesting structure:

WordCloud@
  AssociationThread[
    Rest@Normal@wriVids["items", All, "snippet", "title"],
    Rest@ToExpression@Normal@wriStats["items", All, "statistics", "viewCount"]
    ]

(*Out:*)

post22-978266547142309807

And it seems that people really like the basics and...really like seismic waves?

I'll embed the first of those so we can see how good the really are:

$so["EmbedIFrame", "id"->wriVids["items", 3, "id", "videoId"]]

(* Out *)
<iframe id="ytplayer" type="text/html" width="640" height="360"
src="https://www.youtube.com/embed/2rYjlVPU9U4?autoplay=0"
  frameborder="0"></iframe>

Uploading Videos

A YouTube API wouldn't be much of a YouTube API if it couldn't upload videos, of course, so I cooked that in as well.

Here's a sample of that. We'll first pull an animation off the Manipulate docs:

anim =
  Export[
    FileNameJoin@{$TemporaryDirectory, "plot3d.flv"},
    Manipulate[
      Plot3D[Sin[n x y], 
        {x, 0, 3}, {y, 0, 3}, 
        ViewPoint -> Dynamic[{2, v, 2}], SphericalRegion -> True, Ticks -> None,
        PerformanceGoal->"Quality"
        ], 
      {n, 1, 4}, 
      {v, -2, 2}
      ]
    ];

Then we'll upload the video we made:

upload = $so["UploadVideo", "part"->"id", "BodyContent"->anim];

Then we attach a title and things in a second request:

$so["UpdateVideo", "id" -> upload["id"],
 "part" -> "snippet",
  "Title" -> "Mathematica Examples: Plot 3D",
 "CategoryID" -> "22"
 ]

(*Out:*)

post22-4324612576805415951

And then now we'll embed that video we just made:

$so["EmbedIFrame", "id"->upload["id"]]

(* Out *)
<iframe id="ytplayer" type="text/html" width="640" height="360"
src="https://www.youtube.com/embed/Quzcr4Vuq_Q?autoplay=0"
  frameborder="0"></iframe>
6 Replies

enter image description here - Congratulations! This post is now a Staff Pick as distinguished by a badge on your profile! Thank you, keep it coming!

Hats off!! really impressive. Question: isn't there a way simply to get all the urls of your query? This would be quite useful. Even if they can't be played from Mathematica...

Posted 2 months ago

It depends on what you mean by the URLs. You can’t download YouTube videos with the API, but you can get a link to the actual URL on YouTube where the video will display or use some YouTube downloader with that URL to get the video.

"but you can get a link to the actual URL on YouTube where the video will display or use some YouTube downloader with that URL to get the video." Exactly that is what I want. How to do it?

Posted 2 months ago

With a response dataset you can get the ID for the video or list IDs for a list of videos by inspecting the response dataset structure and using the appropriate extractors.

Then you use the request $so["VideoURL", "id"->id] to get the display URL. You can map this over the IDs if you want to get a bunch of URLs.

Thanks for the instruction. I verified that it works on V11.3 win 10.

enter image description here

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract