Soundcloud: How do I know the sound cloud track ID right away after uploading a track? - soundcloud

http://developers.soundcloud.com/docs/api
When I look at the API docs, I see
SC.stream("/tracks/293", function(sound){
sound.play();
});
When I look at the track I uploaded, it only provides me the permalink. How do I get the track ID from the website? Do I always have to do a /resolve to get the ID?

This is probably more manual steps than /resolve, but it is "from the website." The sound id also appears in the embed code when you go to the sound and click "Share".
For example, if you go to a sound page, e.g.:
https://soundcloud.com/lowcountrykingdom/another-ordinary-day
Then click "Share", which brings up a pop up. Click "Embed" to switch to the embed tab, and copy the Embed code, which will look something like:
<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/47580057&color=ff6600&auto_play=false&show_artwork=true"></iframe>
Note the ID in the value of the url query parameter:
url=https%3A//api.soundcloud.com/tracks/47580057

I'd use jquery ajax call to grab the data from Soundcloud. Say you save your variables permalink_url and client_id:
$.get('http://api.soundcloud.com/resolve.json?url='+
permalink_url+'/tracks&client_id='+client_id , function (result) {
console.log(result);
});
This should log an array of the songs. Check out this bin for reference http://jsbin.com/viviza/4/edit
Update: This answer is pretty old.
Soundclick docs https://developers.soundcloud.com/docs/api#uploading
The SC object now allows for getting the id's directly
SC.connect().then(function(){
return SC.get('/me/tracks');
}).then(function(tracks){
return tracks.map(function(track){
console.log("you can log the id here too: " + track.id")
return track.id
})
})

You could also get all the tracks from a given user id. Then use $.map() to place each of the tracks into an array. Call SC.stream() with song[i].id to play a random song from the array from the array of tracks.
SC.get('/users/123456/tracks/', function(tracks) {
// get an array of tracks
var song = $.map(tracks, function(i){
return i;
});
var i = Math.floor(Math.random() * song.length) // get a random value between 0 & the of songs in SC account -1
SC.stream(song[i].id, function(sound){
sound.play();
});
});

Using JavaScript to find the track data from a soundcloud song url:
let trackUrl = 'https://soundcloud.com/user-869590724/talk-to-animals-sentra-remix'
let client_id = '<your-client-id>'
let resolveUrl = `http://api.soundcloud.com/resolve.json?url=${trackUrl}/tracks&client_id=${client_id}`
fetch(resolveUrl, {
method: 'get'
}).then((response) => {
return response.json()
}).then((result) => {
/* now you have the track */
console.log(result)
})

Related

Unexpected behavior for Facebook Sharing [duplicate]

This question already has an answer here:
Facebook ignoring OG image on first share
(1 answer)
Closed 6 years ago.
First of all hi and thanks in advance to anyone who can help with this because I've been going crazy over this for weeks now.
So I've got a website which lists gif taken from my mobile application (which are then stored on AWS and my visitors ( I haven't found a use for me to have users) can share these gifs on facebook using the facebook sdk.
The problem appears when I try sharing an image for the first time
This is what the share dialog shows the first time I click on my sharing button:
http://i.stack.imgur.com/lNVNF.png
and then I close and reclick the same button and now it works:
http://i.stack.imgur.com/YsDUm.png
Now I've been trying to find a way to make this work on the first sharing attempt but to no avail.
I am using meteor in combination with biasport:facebook-sdk and Amazon S3 for the hosting of my files.
Edit here is the code used:
FRONT SIDE
HTML
<div class="facebook share">
<img src="/gallery/fb.png">
</div>
Javascript
Template.*templateName*.events({
'click .facebook': function(e){
e.preventDefault();
e.stopPropagation();
// this is in a modal so I store the data I need
// (events have photos which in turn contain a url to the gif
var url = Session.get('event').photos[Session.get("id")].url;
FB.ui({
method: 'share',
href: url
});
}
SERVER SIDE
JAVASCRIPT
if(Meteor.isClient) {
window.fbAsyncInit = function() {
FB.init({
appId : 'APP_ID',
status : true,
xfbml : true,
version : 'v2.5'
});
};
}
Edit: I found a manual solution using exec future and curl
so first I added a call to a meteor method on the share that updates the facebook crawler
JAVASCRIPT
Template.*templateName*.events({
'click .facebook': function(e){
e.preventDefault();
e.stopPropagation();
// this is in a modal so I store the data I need
// (events have photos which in turn contain a url to the gif
var url = Session.get('event').photos[Session.get("id")].url;
Meteor.call('updateCrawler', url, function(){
FB.ui({
method: 'share',
href: url
});
});
}
Then I defined my meteor method as such
JAVASCRIPT
Meteor.methods({
updateCrawler: function(url){
var future = new Future();
cmd = 'curl -X POST -F "id=' + url + '" -F "scrape=true" -F "access_token={my_access_token}" "https://graph.facebook.com"';
exec(cmd, function(error){
if (error){
console.log(error);
}
future.return();
});
future.wait();
}
});
it's ugly but since I'd have to wait for the crawler to update and it works I'll leave this here for future use for someone maybe
Edit2:
I did not use og tags at all since I was simply sharing a url to aws directly and not a url to my website
I worked around this problem by calling the Facebook API direct from the server to make it scrape the og data by requesting info on the page. First time round it doesn't have the image cached but second time it does so this workaround does the initial call before sharing.
Use an access token for your facebook app and call the below in an ajax call and await the response before opening share dialog. Replace Google address with your own uri encoded address https://graph.facebook.com/v2.5/?id=http%3A%2F%2Fwww.google.co.uk&access_token=xxxxx
EDIT:
As per comments, here is my server side method for calling this which I use when posts etc are inserted to make the initial call and prompt a scrape from fb:
var getTheOGInfo = function (link)
{
if (!link || link.slice(0, 4).toLowerCase() != "http"){
throw new Meteor.Error("og-info-bad-url", "Function requires an unencoded fully qualified url");
return false;
}
var url = "https://graph.facebook.com/v2.5/{{{{id}}}}?access_token={{{{token}}}}&fields=og_object{id,description,title,type,updated_time,url,image},id,share";
var token = Meteor.settings.private.fb.token;
if (!token){
throw new Meteor.Error("og-info-no-token", "Function requires a facebook token in Meteor.settings.private.fb.token");
return false;
}
var link_id = encodeURIComponent(link);
url = url.replace('{{{{token}}}}', token).replace('{{{{id}}}}', link_id);
var result = HTTP.get(url, {timeout:1000});
return result;
}
Or for your purposes you may not want anything that might be blocking so you could change the last two lines to be aynchronous:
var result = HTTP.get(url, {timeout:1000});
return result;
//Replace with non blocking
HTTP.get(url, {timeout:1000}, function(err, result){console.log('something asynchronous', err, result);});
return true;

Souncloud soundmanager multiple playlist

Hi i'm using SoundCloud manager, http://www.schillmania.com/projects/soundmanager2/ to play audio files on my website. Following their documentation over here: http://soundcloud-sm2.heroku.com/docs/application.html , i'm able to play a sound cloud playist from a set url.
Now I have multiple sets/ playlist, how can I instantiate a new sound manager class and toggle between them by hidden their elements using css.
Here is the sound manager application code( ideally I would want to create two soundmanager.Createsound())
var consumer_key = "59f0360dads135bd07sdasasdadsad8acc14ae2d929",
url = "https://soundcloud.com/artist-2/sets/owl";
// Resolve the given url and get the full JSON-worth of data from SoundCloud regarding the playlist and the tracks within.
$.getJSON('http://api.soundcloud.com/resolve?url=' + url + '&format=json&consumer_key=' + consumer_key + '&callback=?', function(playlist){
// I like to fill out the player by passing some of the data from the first track.
// In this case, you'll just want to pass the first track's title.
$('.title').text(playlist.tracks[0].title);
// Loop through each of the tracks
$.each(playlist.tracks, function(index, track) {
// Create a list item for each track and associate the track *data* with it.
$('<li>' + track.title + '</li>').data('track', track).appendTo('.tracks');
// * Get appropriate stream url depending on whether the playlist is private or public.
// * If the track includes a *secret_token* add a '&' to the url, else add a '?'.
// * Finally, append the consumer key and you'll have a working stream url.
url = track.stream_url;
(url.indexOf("secret_token") == -1) ? url = url + '?' : url = url + '&';
url = url + 'consumer_key=' + consumer_key;
// ## SoundManager2
// **Create the sound using SoundManager2**
soundManager.createSound({
// Give the sound an id and the SoundCloud stream url we created above.
id: 'track_' + track.id,
url: url,
// On play & resume add a *playing* class to the main player div.
// This will be used in the stylesheet to hide/show the play/pause buttons depending on state.
onplay: function() {
$('.player').addClass('playing');
$('.title').text(track.title);
},
onresume: function() {
$('.player').addClass('playing');
},
// On pause, remove the *playing* class from the main player div.
onpause: function() {
$('.player').removeClass('playing');
},
// When a track finished, call the Next Track function. (Declared at the bottom of this file).
onfinish: function() {
nextTrack();
}
});
});
});

Sharethis & Addthis

Has anyone figured out how to only increment share counts if the sharing action is completed?
They seem to count clicks.. not completed shares. That isn't a stat that is profoundly meaningful to me.
You can set it so the count displays the 'native' count:
<script type="text/javascript">stLight.options({
publisher:"Your publisher key", nativeCount:true
});</script>
However this only seems to work for Facebook, LinkedIn and a few others. For Twitter, I just replace the ShareThis count with the actual count obtained from the Twitter API, once ShareThis has loaded and the ShareThis markup exists on the page:
var pageUrl = 'http://www.google.com/';
updateTwitter();
function updateTwitter() {
if (jQuery('.st_twitter_vcount .stBubble_count').length > 0) {
jQuery.getJSON('http://urls.api.twitter.com/1/urls/count.json?url=' + pageUrl + '&callback=?',
function(data) {
jQuery(".st_twitter_vcount .stBubble_count").html(data.count);
});
}
else {
setTimeout(function() {
updateTwitter();
}, 50);
}
}
Just change the pageURL variable to the URL you want to display statistics for.
Hope that helps,
Kamal.
Ended up rolling my own. Neither seems to support this.

Extjs file upload progress

I have seen form file upload example in ExtJS4 and i need customize progress of the file upload.
I see waitMsg config property, but i don't want use that and i don't want use extjs 3rd party plugins.
So, how i can get simply current upload progress from upload form in extjs?
The waitMsg uses a message box with an infinitely auto-updating progress bar. So you can't just create a progressbar that displays the current upload.
You could create your own Ext.ProgressBar and estimate the upload time and when its done you set it to the max value. But I guess you don't want that.
To answer your question: You cannot simply track the current upload progress.
If you really need this user experience you can try a 3rd party component.
To quote the docs:
File uploads are not performed using normal "Ajax" techniques, that is
they are not performed using XMLHttpRequests. Instead the form is
submitted in the standard manner with the DOM element
temporarily modified to have its target set to refer to a dynamically
generated, hidden which is inserted into the document but
removed after the return data has been gathered.
To show real progress you can use onprogress callback of XMLHttpRequest:
Ext.override(Ext.data.request.Ajax, {
openRequest: function (options) {
var xhr = this.callParent(arguments);
if (options.progress) {
xhr.upload.onprogress = options.progress;
}
return xhr;
}
});
Then use like here:
Ext.Ajax.request({
url: '/upload/files',
rawData: data,
headers: { 'Content-Type': null }, //to use content type of FormData
progress: function (e) {
console.log('progress', e.loaded / e.total);
}
});
See online demo here.
buttons: [{
text: 'Upload',
handler: function () {
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
url: '/upload/file',
waitMsg: 'Uploading your file...',
success: function (f, a) {
var result = a.result,
data = result.data,
name = data.name,
size = data.size,
message = Ext.String.format('<b>Message:</b> {0}<br>' +
'<b>FileName:</b> {1}<br>' +
'<b>FileSize:</b> {2} bytes',
result.msg, name, size);
Ext.Msg.alert('Success', message);
},
failure: function (f, a) {
Ext.Msg.alert('Failure', a.result.msg);
}
});
}
}
}]
Live demo with progress window is here

Soundcloud HTML5 widget continuous play

I'm trying to get the SoundCloud HTML5 player widget to automatically start and seek to a specific track and position but no matter what I try it doesn't work.
I'm using the API code below:
<iframe width="100%" height="450" scrolling="no" id="soundcloud-player" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F3058825&color=00be53&auto_play=false&show_artwork=true"></iframe>
<script type="text/javascript" src="http://w.soundcloud.com/player/api.js"></script>
<script type="text/javascript">
(function(){
var widgetIframe = document.getElementById('soundcloud-player'),
widget = SC.Widget(widgetIframe);
widget.bind(SC.Widget.Events.READY, function() {
widget.play();
widget.seekTo('5000');
});
widget.bind(SC.Widget.Events.PLAY, function() {
// get information about currently playing sound
widget.getCurrentSound(function(currentSound) {
console.log('sound ' + currentSound.title + 'began to play');
});
}); }());
What I'm basically trying to accomplish is have the player automatically seek to the same spot when the user switches between pages on the site. I plan on reading from a cookie, the position and track and then using the method above. Any help would be greatly appreciated!
The problem is most probably related to the sound not being fully loaded at the moment when you are trying to call seekTo. You can easily verify this by adding the following bit to your code:
// …
widget.bind(SC.Widget.Events.READY, function() {
widget.play();
// Note setTimeout here!
// This will now work since the needed part of the sound
// will have loaded after the timeout
setTimeout(function () {
widget.seekTo('5000');
}, 1000);
});
// …
But since you don't really want to have arbitrary timeout in your code, it's a good idea to attach event handler to progress event:
widget.bind(SC.Widget.Events.LOAD_PROGRESS, function onLoadProgress (e) {
if (e.loadedProgress && e.loadedProgress === 1) {
widget.seekTo(15000); // seek to previous location
widget.unbind(SC.Widget.Events.LOAD_PROGRESS);
}
});
Here's a working version of this code http://jsbin.com/ebeboj/2/edit
Also, in case you have very long tracks, you could also retrieve duration from the sound (via getCurrentSound), check at what point in range from 0 to 1 the track has stopped playing and only wait for that value (since loadedProgress === 1 might take a while), something like:
widget.getCurrentSound(function(currentSound) {
// currrentSound.duration is 269896 for the first track of your playlist
relativePreviousPlay = previousPlay / currentSound.duration; // ~0.204
});
widget.bind(SC.Widget.Events.LOAD_PROGRESS, function onLoadProgress (e) {
if (e.loadedProgress && e.loadedProgress > relativePreviousPlay) {
widget.seekTo(previousPlay); // seek to previous location
widget.unbind(SC.Widget.Events.LOAD_PROGRESS);
}
});
Check out working example for the last bit of code here http://jsbin.com/ebeboj/4/edit
Sidenote: I'd recommend using localStorage over cookies for storing previous position of playback, because cookies will travel back and forth from client to server slowing down your website, and you likely don't need the information on the sever side.