UNPKG

7.7 kBMarkdownView Raw
1## YouTube API Experiments
2
3I was playing with the [YouTube Data API](https://developers.google.com/youtube/v3/) and here are some preliminary examples. I'm just trying to get used to the API and generate some nice visuals and links from Music Videos.
4
5### API Key Setup
6
7```javascript/autoplay/playable
8var apiKey = 'AIzaSyBgijm7caYxh--UmpCVj3_Ltq684YgHoYI';
9smartdown.setVariable('APIKey', apiKey);
10smartdown.setVariable('videoCategoryId', '10');
11
12```
13
14[API Key](:?APIKey)
15
16### Get Video Categories
17
18Using the [YouTube Data API Explorer](https://developers.google.com/apis-explorer/?hl=en_US#p/youtube/v3/), we discover that the function [youtube.videos.list](https://developers.google.com/apis-explorer/?hl=en_US#p/youtube/v3/youtube.videos.list) seems to be a good way to list videos, but that you need to restrict it with a `videoCategoryId`. So let's see what the available video category Ids exist by using the [youtube.videoCategories.list](https://developers.google.com/apis-explorer/?hl=en_US#p/youtube/v3/youtube.videoCategories.list).
19
20#### Get JSON Result
21
22Since this is a Smartdown document, we'll save the JSON results in a Smartdown variable called `CategoriesJSON` and display those results in a table.
23
24```javascript/autoplay/playable
25this.dependOn = ['APIKey'];
26this.depend = function() {
27 var apiKey = env.APIKey;
28
29 var url = `https://www.googleapis.com/youtube/v3/videoCategories?part=snippet&regionCode=US&key=${apiKey}`;
30
31 var xhr = new XMLHttpRequest();
32 xhr.withCredentials = false;
33 xhr.addEventListener("load", function() {
34 var sourceText = this.responseText;
35 var json = JSON.parse(sourceText);
36 smartdown.setVariable('CategoriesJSON', json, 'json');
37 });
38 xhr.open("GET", url);
39 xhr.send();
40};
41
42```
43
44[](:!CategoriesJSON)
45
46#### Format JSON as a List
47
48We could format the JSON as a Markdown table, but it will be more compact to just generate a list of `name/id` pairs.
49
50```javascript/playable/autoplay
51this.dependOn = ['CategoriesJSON'];
52this.depend = function() {
53 console.log('CategoriesJSON depend', env.CategoriesJSON);
54 var json = env.CategoriesJSON;
55
56 let list = '';
57 var items = json.items;
58 items.forEach(item => {
59 var snippet = item.snippet;
60 list += `\`${snippet.title}/${item.id}\` `;
61 });
62
63 smartdown.setVariable('CategoriesList', list);
64};
65
66```
67
68[Category/Id Pairs](:!CategoriesList|markdown)
69
70
71### Get a list of Music Videos
72
73The table above indicates that category id `10` corresponds to `Music`, and that id `1` corresponds to `Film & Animation`. After experimenting with the API, I've found that many of the categories appear to be empty. So to provide some flexibility, we'll store the category id in a Smartdown variable called `videoCategoryId` and add an input cell and add a few convenience buttons so that you can change it if you want and the video list will be recomputed. I've included buttons for the categories I've tried that contain videos.
74
75[Film & Animation](:=videoCategoryId=1) [Autos & Vehicles](:=videoCategoryId=2) [Music](:=videoCategoryId=10) [Sports](:=videoCategoryId=17) [Travel & Events](:=videoCategoryId=19) [Gaming](:=videoCategoryId=20) [Comedy](:=videoCategoryId=23) [Entertainment](:=videoCategoryId=24) [Howto & Style](:=videoCategoryId=26) [Science & Technology](:=videoCategoryId=28)
76
77[Video Category Id](:?videoCategoryId)
78
79
80#### Get JSON Results
81
82```javascript/playable/autoplay
83this.dependOn = ['videoCategoryId', 'APIKey'];
84this.depend = function() {
85 var maxResults = 5;
86 var apiKey = env.APIKey;
87 var videoCategoryId = env.videoCategoryId;
88 var url = `https://www.googleapis.com/youtube/v3/videos?part=snippet&maxResults=${maxResults}&chart=mostPopular&videoCategoryId=${videoCategoryId}&key=${apiKey}`;
89
90 var xhr = new XMLHttpRequest();
91 xhr.withCredentials = false;
92 xhr.addEventListener("load", function() {
93 var sourceText = this.responseText;
94 var json = JSON.parse(sourceText);
95 smartdown.setVariable('VideosJSON', json, 'json');
96 });
97 xhr.open("GET", url);
98 xhr.send();
99};
100```
101
102[](:!VideosJSON)
103
104#### Format JSON as a List
105
106```javascript/playable/autoplay
107this.dependOn = ['VideosJSON'];
108this.depend = function() {
109 var videosJSON = env.VideosJSON;
110 var items = videosJSON.items;
111 let list = '\n\n|Video|Title|Tags|\n|:---:|:---|:---|\n';
112
113 items.forEach(item => {
114 var snippet = item.snippet;
115 var thumb = snippet.thumbnails.default.url;
116 var thumbMax = snippet.thumbnails.maxres ?
117 snippet.thumbnails.maxres.url :
118 snippet.thumbnails.high.url;
119 var tags = '';
120 snippet.tags.forEach(tag => {
121 tags += `${tag} `;
122 });
123 var vidLink = `https://www.youtube.com/watch?v=${item.id}`;
124 var cleanTitle = snippet.title.replace(/[\n\r|]/g, 'Y');
125 var line = `|![thumbnail](${vidLink})|**${cleanTitle}**|${tags}|\n`;
126 list += line;
127 });
128 list += '\n\n';
129
130 smartdown.setVariable('VideosList', list, 'markdown');
131};
132```
133
134#### Display the List of Videos
135
136[](:!VideosList|markdown)
137
138
139### Data Visualization - Word Cloud
140
141Let's accumulate the `tags` for each video and build a word cloud!
142
143#### Get Tags
144
145```javascript/playable/autoplay
146this.dependOn = ['VideosJSON'];
147this.depend = function() {
148 var videosJSON = env.VideosJSON;
149 var items = videosJSON.items;
150 let list = '\n\n';
151
152 tagCounts = {};
153
154 items.forEach(item => {
155 item.snippet.tags.forEach(tag => {
156 tagCounts[tag] = (tagCounts[tag] || 0) + 1;
157 });
158 });
159
160 tagList = [];
161 for (var tag in tagCounts) {
162 var count = tagCounts[tag];
163 tagList.push({
164 text: tag,
165 size: 50 * count * count, // 20 + 10 * count * count * count * count
166 });
167 }
168
169 smartdown.setVariable('TagList', tagList);
170};
171
172```
173
174[](:!TagList|json)
175
176
177#### Draw Them
178
179```d3/playable/autoplay
180var renderDiv = this.div;
181this.dependOn = ['TagList'];
182this.depend = function() {
183 renderDiv.innerHTML = '';
184 renderDiv.style.margin = 'auto';
185 renderDiv.style.width = '100%';
186 renderDiv.style.height = '100%';
187 var bounds = renderDiv.getBoundingClientRect();
188 console.log('bounds', bounds);
189 var width = bounds.width;
190
191 var d3 = smartdown.d3v4;
192 var cloud = smartdown.d3cloud;
193 words = env.TagList;
194
195 var fill = d3.scaleOrdinal(d3.schemeCategory20);
196 var layout = cloud()
197 .size([width, width])
198 .words(words)
199 .padding(5)
200 .rotate(function() { return ~~(Math.random() * 2) * 90; })
201 .font("Impact")
202 .fontSize(function(d) { return d.size; })
203 .on("end", draw);
204
205 layout.start();
206
207 function draw(words) {
208 d3.select(renderDiv).append("svg")
209 .attr("width", layout.size()[0])
210 .attr("height", layout.size()[1])
211 .append("g")
212 .attr("transform", "translate(" + layout.size()[0] / 2 + "," + layout.size()[1] / 2 + ")")
213 .selectAll("text")
214 .data(words)
215 .enter().append("text")
216 .style("font-size", function(d) { return d.size + "px"; })
217 .style("font-family", "Impact")
218 .style("fill", function(d, i) { return fill(i); })
219 .attr("text-anchor", "middle")
220 .attr("transform", function(d) {
221 return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
222 })
223 .text(function(d) { return d.text; });
224
225 window.setTimeout(function() {
226 renderDiv.scrollIntoView();
227 }, 1000);
228 }
229};
230
231```
232
233
234[Film & Animation](:=videoCategoryId=1) [Autos & Vehicles](:=videoCategoryId=2) [Music](:=videoCategoryId=10) [Sports](:=videoCategoryId=17) [Travel & Events](:=videoCategoryId=19) [Gaming](:=videoCategoryId=20) [Comedy](:=videoCategoryId=23) [Entertainment](:=videoCategoryId=24) [Howto & Style](:=videoCategoryId=26) [Science & Technology](:=videoCategoryId=28)
235
236
237---
238
239[Back to Home](:@Home)
240
241