Using playlistitem.insert via one link - excel

I've been able to do video searches and read info using just one link that starts with googleapis.com but for the playlistitemsinsert to put videos into a playlist, I'm having trouble with the syntax. I'm trying to randomize the order of videos in a YouTube playlist. I understand you can shuffle play but its easier for me to remove the videos if they're played in chronological order, also its easier to go back to a video you recently watched.
I have all of the video ids in a column in excel I'm just not sure how to use vba to do a POST HTTP request to insert the videos into a playlist. Can you help me with the syntax on this?

Although not using excel as database This works using youtube api. and users youtube created play list . shuffles the play list into new order every time page is refreshes
Load YT-player API.
Load YT-playlist user playlist id "**.youtube.com/playlist?list=PLo16_*******"
To Shuffle playlist use > player.setShuffle(true);
To Start YT-player at video 1 in shuffled playlist use > player.playVideoAt(0)
working demo Responsive shuffled YouTube Playlist on Google sites
code jsfiddle.net
<!DOCTYPE html>
<html>
<!-- Responsive YouTube shuffled playlist player -->
<head>
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag.
style = replaces size in the player script makes it responsive -->
<div style=" top: 0; left: 0; width: 100%; height: 100%; position: absolute;"
id='player'>
</div>
</body>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
playerVars: {
autoplay: 0,
loop: 1,
controls: 1,
showinfo: 1,
frameborder: 1,
'listType': 'playlist',
'list': "PLo16_DLriHp4A8BvkJFZfO_4KDVv7yGgy", // your YouTube playlist id here
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
// first shuffle play list
player.setShuffle(true);
// Onload and on refresh shuffles the users YT playlist but always starts playing
// the first video in the original list at its new index position
//ie. video (1) = video( new shuffled pos ?)
// to get over this we can start the player at the new shuffled playlist
//video 1(index=0) this changes every time it's refreshed
player.playVideoAt(0)
}
// 5. The API calls this function when the player's state changes.
// option to to add bits
function onPlayerStateChange(event) {
const player = event.target;
}
</script>
</html>

Related

Is there a way to play background music using Google Apps Script?

I am creating an add-on which would ask the user to select music from a list and it would play it as background music. But previous posts show a sidebar with the user manually pressing the play button. I am wondering if there is a way to play it with Google Apps Script only. Also what would be helpful is if there was a volume property to set the volume?
My Code:
function onOpen(){
DocumentApp.getUi()
.createMenu("Background Music Add-On")
.addItem("Select Music","music")
.addItem("Set Volume","musicVol")
.addToUi();
}
//music selection
function music(){
var musicName = DocumentApp.getUi()
.prompt("Please select one of the music names:\n\nElevator Music,\nLeaf Rag.\nso on...")
switch(musicName){
case "Elevator":
//code to play music Elevator
break;
//So On
}
}
Playing music from a Playlist stored on your Google Drive
This script allows you to store mp3's on your Google Drive. It allows you to select which files you wish to listen too via a playlist. You must start the playlist the first time manually but then the rest of the selections play automatically. The script converts the mp3 files into dataURI's and loads them into the audio element. You can skip over the current selection and you can restart the playlist when it completes.
Code.gs
function onOpen() {
SpreadsheetApp.getUi().createMenu('My Music')
.addItem('Launch Music', 'launchMusicDialog')
.addItem('Create New Music List', 'createMusicList')
.addToUi();
}
function convMediaToDataUri(filename){
var filename=filename || "default.mp3";
var folder=DriveApp.getFolderById("Music Folder Id");
var files=folder.getFilesByName(filename);
var n=0;
while(files.hasNext()) {
var file=files.next();
n++;
}
if(n==1) {
var blob=file.getBlob();
var b64DataUri='data:' + blob.getContentType() + ';base64,' + Utilities.base64Encode(blob.getBytes());
Logger.log(b64DataUri)
var fObj={filename:file.getName(),uri:b64DataUri}
return fObj;
}
throw("Multiple Files with same name.");
return null;
}
function launchMusicDialog() {
var userInterface=HtmlService.createHtmlOutputFromFile('music1');
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Music');
}
function createMusicList() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("MusicList");
var folder=DriveApp.getFolderById("Music Folder Id");
var files=folder.getFiles();
var mA=[['Item','File Name','File Type','File Id','Play List']];
sh.clearContents()
var n=1;
while(files.hasNext()) {
var file=files.next();
mA.push([n++,file.getName(),file.getMimeType(),file.getId(),'']);
}
sh.getRange(1,1,mA.length,mA[0].length).setValues(mA);
sh.getRange(2,2,sh.getLastRow()-1,sh.getLastColumn()-1).sort({column:2,ascending:true});
sh.getRange(2,5,sh.getLastRow()-1,1).insertCheckboxes();
}
function getPlaylist() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('MusicList');
var rg=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn());
var vA=rg.getValues();
var pl=[];
for(var i=0;i<vA.length;i++) {
if(vA[i][4]) {
pl.push(vA[i][1]);
}
}
return pl;
}
music1.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
label{margin:2px 10px;}
</style>
</head>
<script>
var selectionList=[];
var gVolume=0.2;
var index=0;
$(function(){
document.getElementById('msg').innerHTML="Loading Playlist";
google.script.run
.withSuccessHandler(function(pl){
selectionList=pl;
console.log(pl);
google.script.run
.withSuccessHandler(function(fObj){
$('#audio1').attr('src',fObj.uri);
var audio=document.getElementById("audio1");
audio.volume=gVolume;
audio.onended=function() {
document.getElementById('status').innerHTML='Ended...';
playnext();
}
var msg=document.getElementById('msg');
msg.innerHTML="Click play to begin playlist. Additional selections will begin automatically";
audio.onplay=function() {
document.getElementById('msg').innerHTML='Playing: ' + selectionList[index-1];
document.getElementById('status').innerHTML='Playing...';
document.getElementById('skipbtn').disabled=false;
}
audio.onvolumechange=function(){
gVolume=audio.volume;
}
})
.convMediaToDataUri(selectionList[index++]);
})
.getPlaylist();
});
function playnext() {
if(index<selectionList.length) {
document.getElementById('status').innerHTML='Loading...';
document.getElementById('msg').innerHTML='Next Selection: ' + selectionList[index];
google.script.run
.withSuccessHandler(function(fObj){
$('#audio1').attr('src',fObj.uri);
var audio=document.getElementById('audio1');
audio.volume=gVolume;
audio.play();
})
.convMediaToDataUri(selectionList[index++]);
}else{
document.getElementById('status').innerHTML='Playlist Complete';
document.getElementById('msg').innerHTML='';
document.getElementById('cntrls').innerHTML='<input type="button" value="Replay Playlist" onClick="replayPlaylist()" />';
}
}
function replayPlaylist() {
index=0;
document.getElementById('cntrls').innerHTML='';
playnext();
}
function skip() {
var audio=document.getElementById('audio1');
document.getElementById('skipbtn').disabled=true;
audio.pause();
index++;
playnext();
}
</script>
<body>
<div id="msg"></div>
<audio controls id="audio1" src=""></audio><br />
<div id="status"></div>
<div><input type="button" id="skipbtn" value="Skip" onClick="skip()" disabled /></div>
<div id="cntrls"></div>
</body>
</html>
Please read through the code. You need to add a music folder id and a couple of default.mp3's. The createMusicList() function reads your Music Folder and Loads them into a sheet named 'MusicList' with columns of "Item", "File Name", "File Type" ,"File Id", and PlayList. The last column is just a column of unchecked checkboxes for you to make your current playlist selection. Only one playlist for now, so you can enjoy building your own.
Here's what the dialog looks like:
And here's an image of my MusicList Sheet:
This is where you make your playlist selections.
Audio Properties and Methods
Apps Script Documentation
Latest Script Code
I used the answer to this question as a starting point: playing sound with google script
You would need to open a html sidebar and use an audio tag, to do this you can use the HtmlService class [1].
As a total background you can't, the sidebar must be always open to play the music. But you could still play the audio while editing the document.
To add the audio setting you can add the controls attribute to the audio tag [2]. For playing the audio automatically you can add the autoplay attibute [3].
Here is the code I implemented to achieve your goal. The code gets the selected value and uses it to change the autoplay value to true and to display the audio as well. Also, when the select element is on focus, it gets the previous selected value so later (when a new value is selected) it can be used to stop the previous audio selection and not display it anymore. For these purposes I used the onchange [4] and the onfocus [5] events.
Code.gs
var SIDEBAR_TITLE = 'Sidebar Musicbox';
function onOpen(e) {
DocumentApp.getUi()
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle(SIDEBAR_TITLE);
DocumentApp.getUi().showSidebar(ui);
}
Sidebar.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div class="sidebar branding-below">
<p>
A little music for your enjoyment!
</p>
<form>
<select id="music" onchange="playSelection();" onfocus="setOldValue(this.value);">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</form>
<br>
<audio id="player0" controls style="display:none">
<source src="[WEB-URL-FOR-MP3-FILE]" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<audio id="player1" controls style="display:none">
<source src="[WEB-URL-FOR-MP3-FILE]" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<audio id="player2" controls style="display:none">
<source src="[WEB-URL-FOR-MP3-FILE]" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<br>
<div id="sidebar-status"></div>
</div>
<div class="sidebar bottom">
<span class="gray branding-text">Docs Add-on Sound Demo</span>
</div>
</body>
<script>
var previousValue;
//Function called when select onFocus
function setOldValue(e) {
previousValue = e;
}
//Function called when selected value change
function playSelection() {
//Get the value for the selected option
var selectedValue = document.getElementById("music").value;
//Latest and previous selection IDs
var player = "player" + selectedValue;
var previousPlayer = "player" + previousValue;
//Stop and don't display the previous selection of audio
document.getElementById(previousPlayer).style.display = "none";
document.getElementById(previousPlayer).autoplay = false;
document.getElementById(previousPlayer).load();
//Play and display the new selection and put the focus on it
document.getElementById(player).style.display = "block";
document.getElementById(player).autoplay = true;
document.getElementById(player).load();
document.getElementById(player).focus();
}
</script>
</html>
[1] https://developers.google.com/apps-script/guides/html/
[2] https://www.w3schools.com/tags/att_audio_controls.asp
[3] https://www.w3schools.com/tags/att_audio_autoplay.asp
[4] https://www.w3schools.com/jsref/event_onchange.asp
[5] https://www.w3schools.com/jsref/event_onfocus.asp

How to load YouTube API locally?

I need to load the YouTube API locally (Google Extension not allowing external scripts). So I downloaded the files into my directory:
https://www.youtube.com/player_api
https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js
However, when I try to programmatically inject this via a content script, it gives the following error:
Uncaught ReferenceError: YTConfig is not defined
To the OP: You were almost there! I'd like to acknowledge Jonathan Waldman, MSDN author, for mentioning this technique during one of his training sessions...
To review, YTConfig is defined at:
http://www.youtube.com/iframe_api
And here:
http://www.youtube.com/player_api
The iframe_api is the preferred link to use.
To recap, the links you provide above each link to JS code:
https://www.youtube.com/player_api
https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js
You also need a Div tag with an id of "player" and another Script tag that lets you specify which video you want to see. So there are four Script tags total:
For content in iframe_api
For content at https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js
For the player Div tag:
<div id="player"></div>
For JavaScript that configures the video
This translates loosely to:
<script>...place the player Div here</script>
<script>...place code from www-widgetapi-vfl4qCmf3.js here...</script>
<script>...place code from iframe_api here...</script>
<script>...place the code below here</script>
Here is the code for the final Script tag (note that you will likely want to change the videoId property so that it points to the ID of the desired video on the YouTube site):
<script>
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
When I did the above, the page worked and I had all of the YouTube code local to my development machine.

iOS7 UIWebivew Youtube MPMediaPlayer not working

I need to play a video within an UIWebiview which comes from youtube.
Everything was working fine on older devices (5.1+)
Unfortunately on iOS7 the video is not playing. It starts loading but it'll never start playing. Even if the video has fully been loaded. Only if you stop and press play manually the video starts playing.
Here's some code:
- (void)viewDidAppear:(BOOL)animated;
{
[super viewDidAppear:animated];
if(!self.viewMoviePlayerView.superview) {
[self.viewMediaContentContainer addSubview:self.viewMoviePlayerView];
}
self.viewMoviePlayerView.isScrollingEnabled = NO;
[self.viewMoviePlayerView loadRequest:[NSURLRequest requestWithURL:
[NSURL URLWithString:
[NSString stringWithFormat:#"%#%#", #"http://www.youtube.com/embed/", self.currentSelectedItem.guid]]]];
...
}
Any suggestions on that?
Autoplay is not allowed on recent versions of iOS. You don't suppose to programmatically start downloading data that could cause a cost to the user. I found a way but it's a little tricky:
Show an html string in stead of an url
[webview loadHTMLString:<html> baseURL:[[NSBundle mainBundle] resourceURL]];
The html needs to be an embed player:
<html>
<body style='margin:0px;padding:0px;'>
<script type='text/javascript' src="http://www.youtube.com/iframe_api"></script>
<script type='text/javascript'>
function onYouTubeIframeAPIReady(){
ytplayer=new YT.Player('playerID',{events:{onReady:onPlayerReady, onStateChange:onPlayerStateChange}});
}
function onPlayerReady(a){ a.target.playVideo(); }
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.BUFFERING) {
event.target.playVideo();
}
}
</script>
<iframe id='playerID' type='text/html' width='320' height='240'
src="http://www.youtube.com/embed/xxxxxxxxxxx?enablejsapi=1&rel=0&playsinline=1&autoplay=1" frameborder='0'></iframe>
</body>
</html>
this works fine because the javascript in the iframe API it forces the player to start playing once it loads and every time it starts buffering. I strongly suggest you to read about the youtube API
Put your video id in the embed and thats it!

Immediate play sound on button click in HTML page

In my HTML page I have 9 images for dialing numbers and one text box that shows the pressed numbers. I want each of those images to immediately play beep sound when users click on them. I tried to use embed with hidden property and navigate it's source to .wav sound.
It is working OK, but when I press the images one after another immediately, it cannot play sound and just bees once at the end.
Is there any faster way of playing a .wav sound on 'onclick' method?
If you only need to support recent browsers, then HTML 5 offers you the Audio object
to load/buffer your sound:
var snd = new Audio("file.wav");
to play the sound:
snd.play();
to re-cue it to the beginning (so that you can play it again):
snd.currentTime=0;
This answer https://stackoverflow.com/a/7620930/1459653 by #klaustopher (https://stackoverflow.com/users/767272/klaustopher) helped me. He wrote:
HTML5 has the new <audio>-Tag that can be used to play sound. It
even has a pretty simple JavaScript Interface:
<audio id="sound1" src="yoursound.mp3" preload="auto"></audio>
<button onclick="document.getElementById('sound1').play();">Play
it</button>
Here's how I implemented his advice so that clicking on the Font Awesome icon "fa-volume-up" (located on the Web page after "mule.") results in "donkey2.mp3" sound playing (note: mp3 doesn't play in all browsers).
<p>In short, you're treated like a whole person, instead of a rented mule. <audio id="sound1" src="assets/donkey2.mp3" preload="auto"></audio><a class="icon fa-volume-up" onclick="document.getElementById('sound1').play();"></a>
You can use embed element for play sounds, but you've to check the formats supported by the different browsers.
Embed element on MDN
<a onclick="playSound('1.mp3')">
<img src="1.gif">
</a>
<div id="sound"></div>
<script>
var playSound = function (soundFile) {
$("#sound").html("<embed src=\"" + soundFile + "\" hidden=\"true\" autostart=\"true\" />");
}
</script>
This code lets you put in a picture button; when click you get a sound. It works with Google Chrome and Microsoft Edge but I can't get it to work in Internet Explorer. I'm using html 5 codes; please copy and paste and add you own samples.
</head>
<body>
<script>
var audio = new Audio("/Sample.wav ");
audio.oncanplaythrough = function ( ) { }
audio.onended = function ( ) { }
</script> <input type="image" src="file://C:/Sample.jpg" onclick="audio.play ( )">
</body>
</html>
more on codes look at
http://html5doctor.com/html5-audio-the-state-of-play/
Example based on accepted answer (Tested in Chrome 70), but I didn't need to re-cue:
<button onclick="snd.play()"> Click Me </button>
<script>
var snd = new Audio("/Content/mysound.wav");
</script>
This is what I would do to play sound effects:
<html>
<body>
<audio id="sfx"><source src="mysound.mp3"></audio>
<button onclick="playsound()" id="button">Play a sound!</button>
<script> function playsound() {
var sfx = document.getElementById("sfx");
sfx.autoplay = 'true';
sfx.load();}
Or you can run this snippet:
function playsound() {
var mysound = document.getElementById("mysound");
mysound.autoplay = 'true';
mysound.load();
}
button {
color: blue;
border-radius: 24px;
border: 5px solid red;
}
body {
background-color: #bfbfbf;
}
<html>
<body>
<audio id='mysound'><source src="click.mp3"><!-- "click.mp3" isn't a sound effect uploaded to the snippet, because I don't think you can upload sfx to snippets. (I'm new to stackoverflow, so there might be a way) But if you actually use a sound effect in that folder that you're using, it works. --></audio>
<button id='btn' onclick='playsound()'>Play a sound!</button>
</body>
</html>

Spotify apps tabs - update cache

I'm trying to display a div inside tab playlists if the href contains a spotifyURI. This will be used to display a playlist under a tab.
Step by step this is my problem:
Click playlist tab and then click the "My playlist1".
The href is displayed in the playlist container under the tab playlists. (perfect so far)
Click the start tab and then click the playlists tab.
Instead of displaying the list of playlists the playlist container is show again. So the last used url is cached?
Then if the playlists tab is clicked again the url will be "reseted" and the list of playlists will be shown and playlist container hidden.
I'd like 4. to show the playlist list right away instead.
Is there a way to reset or what am I missing?
<script>
$(document).ready(function() {
sp = getSpotifyApi(1);
var m = sp.require("sp://import/scripts/api/models");
updateTabs();
m.application.observe(m.EVENT.ARGUMENTSCHANGED, updateTabs);
function updateTabs()
{
console.log(m.application.arguments);
var args = m.application.arguments;
$('.section').hide();
if (args[1] == "spotify") $("#playlist").html("args:"+args).show();
else $("#"+args[0]).show();
}
});
</script>
<div id="playlist" class="section">Container for playlist content</div>
<div id="start" class="section">Welcome</div>
<div id="playlists" class="section">
My playlist1
My playlist2
</div>
Thanks alot for all replys!
Here is how I will proceed using JQuery.
First of all you need to use the Localstorage :
var stor = sp.require("sp://import/scripts/storage");
Then if for exemple you get a list of playlist you can build the list like this
for (var i=0; i<d.playlists.length; i++) {
$('#playlists').append('My <a id="p' + i + '"href="'+ d.playlists[i] +'">playlist1</a>');
$('#playlists #p'+i).live('click', function(e) {
e.preventdefault();
stor.set('choosenplaylist', d.playlists[i]);
});
}
This was for the storage now for when changing tad :
if (!stor.get('choosenplaylist')=='') {
location.href=stor.get('choosenplaylist');
}
Okay this is a suggestion and it need to be tested regarding to your app.
Im trying this out now, and i can reproduce your bug (im guessing it's a bug, the tab should replace the url in my opinion)
But, until it's fixed, my best guess is to capture the playlist links in an event handler and cancelling the original event, after cancelling you replace the content with the appropriate playlist view.
Tab test code (on gist.github.com)
I've abstracted the actual view binding from the event handler, and added a click event hook that calls the abstract view binder instead of the "real" one, this also supports deep linking into the an app

Resources