Iframe embed
<iframe
title="SoundCloud playlist player"
width="100%"
height="450"
loading="lazy"
scrolling="no"
frameborder="no"
allow="autoplay"
src="https://w.soundcloud.com/player/?url=ENCODED_PLAYLIST_URL&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false">
</iframe>
Single page code (html + css + js) simple-player.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Simple SoundCloud Player</title>
<style>
body{ font-family:system-ui,Arial; padding:18px; background:#fafafa; }
.player{ max-width:720px; margin:0 auto; background:#fff; padding:12px; border-radius:8px; box-shadow:0 6px 24px rgba(0,0,0,0.06); }
.controls{ display:flex; gap:8px; margin-top:10px; align-items:center; flex-wrap:wrap; }
button{ background:#ff5500; color:#fff; border:none; padding:8px 12px; border-radius:6px; cursor:pointer; }
input[type="url"]{ flex:1; padding:8px; border-radius:6px; border:1px solid #ddd; }
</style>
</head>
<body>
<div class="player">
<h2>Simple SoundCloud Player</h2>
<iframe id="sc" width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay"
src="https://w.soundcloud.com/player/?url=https%3A//soundcloud.com/forss/flickermood&auto_play=false"></iframe>
<div class="controls">
<button id="play">Play</button>
<button id="pause">Pause</button>
<input id="url" type="url" placeholder="SoundCloud track/playlist URL">
<button id="load">Load & Play</button>
</div>
</div>
<script src="https://w.soundcloud.com/player/api.js"></script>
<script>
var widget = SC.Widget(document.getElementById('sc'));
document.getElementById('play').addEventListener('click', function(){ widget.play(); });
document.getElementById('pause').addEventListener('click', function(){ widget.pause(); });
document.getElementById('load').addEventListener('click', function(){
var url = document.getElementById('url').value.trim();
if (!url) return alert('Enter a SoundCloud URL');
widget.load(url, { auto_play: true });
});
</script>
</body>
</html>
control soundcloud using js - player.js
// player.js — accessible SoundCloud widget + playlist with localStorage persistence
// Requires https://w.soundcloud.com/player/api.js to be loaded first.
(function () {
// Storage keys
var STORAGE_KEY = 'sc_playlist_v1';
var STORAGE_SEL_KEY = 'sc_playlist_sel_v1';
// Utils
function msToTime(ms) {
if (ms == null) return '00:00';
var total = Math.floor(ms / 1000);
var s = total % 60;
var m = Math.floor(total / 60);
return String(m).padStart(2, '0') + ':' + String(s).padStart(2, '0');
}
// Safe JSON helpers
function saveJSON(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
console.warn('Failed to save to localStorage', e);
}
}
function loadJSON(key) {
try {
var raw = localStorage.getItem(key);
if (!raw) return null;
return JSON.parse(raw);
} catch (e) {
console.warn('Failed to parse localStorage item', key, e);
return null;
}
}
// Elements
var iframe = document.getElementById('sc-widget');
if (!iframe) return;
var widget = SC.Widget(iframe);
var btnPlay = document.getElementById('btn-play');
var btnPause = document.getElementById('btn-pause');
var btnToggle = document.getElementById('btn-toggle');
var btnSeekBack = document.getElementById('btn-seek-back');
var btnSeekFwd = document.getElementById('btn-seek-fwd');
var volume = document.getElementById('volume');
var position = document.getElementById('position');
var btnLoad = document.getElementById('btn-load');
var trackUrlInput = document.getElementById('track-url');
var trackTitle = document.getElementById('track-title');
var playlistEl = document.getElementById('playlist');
var addUrlInput = document.getElementById('new-track-url');
var btnAdd = document.getElementById('btn-add');
var btnClear = document.getElementById('btn-clear');
// Sample playlist (used only if no saved playlist exists)
var defaultPlaylist = [
{ url: 'https://soundcloud.com/forss/flickermood', label: 'Forss — Flickermood' }
];
// Load playlist from storage or fallback to default
var stored = loadJSON(STORAGE_KEY);
var playlist = Array.isArray(stored) && stored.length ? stored : defaultPlaylist.slice();
// Persist selected index (so selection survives reload)
var storedSel = loadJSON(STORAGE_SEL_KEY);
var selectedIndex = (typeof storedSel === 'number' && storedSel >= 0 && storedSel < playlist.length) ? storedSel : 0;
// Render playlist
function renderPlaylist() {
playlistEl.innerHTML = '';
playlist.forEach(function (item, idx) {
var li = document.createElement('li');
li.className = 'playlist-item';
li.setAttribute('role', 'option');
li.setAttribute('tabindex', '0');
li.setAttribute('data-url', item.url);
li.setAttribute('data-index', String(idx));
li.setAttribute('aria-selected', (idx === selectedIndex) ? 'true' : 'false');
li.innerHTML = '<span class="label">' + escapeHtml(item.label || item.url) + '</span>' +
'<div style="display:flex;gap:6px">' +
'<button class="btn-load-inline" title="Load this track" aria-label="Load ' + escapeForAria(item.label || item.url) + '">Load</button>' +
'<button class="btn-remove-inline" title="Remove from playlist" aria-label="Remove ' + escapeForAria(item.label || item.url) + '">Remove</button>' +
'</div>';
// Click to load or remove
li.addEventListener('click', function (e) {
if (e.target && e.target.classList.contains('btn-load-inline')) {
loadTrack(item.url);
} else if (e.target && e.target.classList.contains('btn-remove-inline')) {
removePlaylistItem(idx);
} else {
setFocusedPlaylistItem(idx);
loadTrack(item.url);
}
});
// Keyboard interaction
li.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
loadTrack(item.url);
} else if (e.key === 'ArrowDown') {
e.preventDefault();
focusNextPlaylistItem(idx);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
focusPrevPlaylistItem(idx);
} else if (e.key === 'Home') {
e.preventDefault();
focusPlaylistItem(0);
} else if (e.key === 'End') {
e.preventDefault();
focusPlaylistItem(playlist.length - 1);
}
});
playlistEl.appendChild(li);
});
// Ensure selectedIndex is valid
if (playlist.length === 0) selectedIndex = -1;
else if (selectedIndex >= playlist.length) selectedIndex = playlist.length - 1;
// Persist playlist and selection
savePlaylist();
saveSelectedIndex();
}
function escapeHtml(s){ return (s+'').replace(/[&<>"']/g, function(m){ return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]; }); }
function escapeForAria(s){ return (s+'').replace(/"/g, "'"); }
function setFocusedPlaylistItem(index) {
var items = playlistEl.querySelectorAll('.playlist-item');
items.forEach(function (el) {
var i = parseInt(el.getAttribute('data-index'), 10);
el.setAttribute('aria-selected', String(i === index));
});
focusPlaylistItem(index);
selectedIndex = index;
saveSelectedIndex();
}
function focusPlaylistItem(index) {
var items = playlistEl.querySelectorAll('.playlist-item');
var el = items[index];
if (el) el.focus();
}
function focusNextPlaylistItem(currentIndex) {
var next = Math.min(playlist.length - 1, currentIndex + 1);
focusPlaylistItem(next);
selectedIndex = next;
saveSelectedIndex();
}
function focusPrevPlaylistItem(currentIndex) {
var prev = Math.max(0, currentIndex - 1);
focusPlaylistItem(prev);
selectedIndex = prev;
saveSelectedIndex();
}
// Save playlist and selected index
function savePlaylist() {
// Only store url + label to avoid extra data
var toStore = playlist.map(function (p) { return { url: p.url, label: p.label || p.url }; });
saveJSON(STORAGE_KEY, toStore);
}
function saveSelectedIndex() {
if (typeof selectedIndex === 'number' && selectedIndex >= 0) saveJSON(STORAGE_SEL_KEY, selectedIndex);
else localStorage.removeItem(STORAGE_SEL_KEY);
}
// Remove an item
function removePlaylistItem(index) {
if (index < 0 || index >= playlist.length) return;
playlist.splice(index, 1);
// adjust selectedIndex if needed
if (selectedIndex === index) selectedIndex = -1;
else if (selectedIndex > index) selectedIndex--;
renderPlaylist();
}
// Load track into widget
function loadTrack(url, opts) {
if (!url) return;
widget.load(url, Object.assign({ auto_play: true, show_artwork: true }, opts || {}));
// Mark selected playlist item if present
var idx = playlist.findIndex(function (p) { return p.url === url; });
if (idx !== -1) {
setFocusedPlaylistItem(idx);
} else {
// not found: clear selection
selectedIndex = -1;
saveSelectedIndex();
// optionally add to playlist? current behavior: do not auto-add
}
}
// Widget ready setup
widget.bind(SC.Widget.Events.READY, function () {
// set initial volume
widget.setVolume(parseInt(volume.value, 10));
// update meta
widget.getCurrentSound(function (sound) {
if (sound && sound.title) trackTitle.textContent = 'Title: ' + sound.title;
});
// position updater
setInterval(function () {
widget.getPosition(function (ms) {
widget.getDuration(function (dur) {
position.textContent = msToTime(ms) + ' / ' + msToTime(dur);
});
});
}, 500);
});
// Playback controls
btnPlay.addEventListener('click', function () { widget.play(); });
btnPause.addEventListener('click', function () { widget.pause(); });
btnToggle.addEventListener('click', function () {
widget.isPaused(function (paused) {
if (paused) {
widget.play();
btnToggle.setAttribute('aria-pressed', 'true');
} else {
widget.pause();
btnToggle.setAttribute('aria-pressed', 'false');
}
});
});
btnSeekBack.addEventListener('click', function () {
widget.getPosition(function (ms) {
var newPos = Math.max(0, ms - 10000);
widget.seekTo(newPos);
});
});
btnSeekFwd.addEventListener('click', function () {
widget.getPosition(function (ms) {
widget.seekTo(ms + 10000);
});
});
volume.addEventListener('input', function () {
var v = parseInt(this.value, 10);
widget.setVolume(v);
});
btnLoad.addEventListener('click', function () {
var url = trackUrlInput.value.trim();
if (!url) {
alert('Enter a SoundCloud track or playlist URL.');
return;
}
loadTrack(url);
// optional: trackUrlInput.value = '';
});
// Update meta on PLAY
widget.bind(SC.Widget.Events.PLAY, function () {
widget.getCurrentSound(function (sound) {
if (sound && sound.title) trackTitle.textContent = 'Title: ' + sound.title;
});
btnToggle.setAttribute('aria-pressed', 'true');
});
widget.bind(SC.Widget.Events.PAUSE, function () {
btnToggle.setAttribute('aria-pressed', 'false');
});
widget.bind(SC.Widget.Events.FINISH, function () {
// optional: advance playlist if loaded from playlist
var selIndex = playlist.findIndex(function (p) { return p.url === currentLoadedUrl; });
if (selIndex !== -1 && selIndex < playlist.length - 1) {
loadTrack(playlist[selIndex + 1].url);
}
});
// Errors
widget.bind(SC.Widget.Events.ERROR, function (e) {
console.warn('SoundCloud widget error', e);
alert('SoundCloud Widget error. The track may be restricted and not embeddable.');
});
// Track currently loaded (best-effort)
var currentLoadedUrl = null;
widget.bind(SC.Widget.Events.READY, function () {
widget.getCurrentSound(function (sound) {
if (sound && sound.permalink_url) currentLoadedUrl = sound.permalink_url;
});
});
widget.bind(SC.Widget.Events.PLAY, function () {
widget.getCurrentSound(function (sound) {
if (sound && sound.permalink_url) currentLoadedUrl = sound.permalink_url;
});
});
// Playlist management UI
btnAdd.addEventListener('click', function () {
var url = addUrlInput.value.trim();
if (!url) return;
playlist.push({ url: url, label: url });
renderPlaylist();
addUrlInput.value = '';
});
btnClear.addEventListener('click', function () {
if (!confirm('Clear all playlist items?')) return;
playlist = [];
selectedIndex = -1;
renderPlaylist();
});
// Global keyboard shortcuts while focus is inside the widget container
var widgetContainer = document.getElementById('widget-container');
widgetContainer.addEventListener('keydown', function (e) {
// Avoid interfering with typing in inputs
var tag = (e.target && e.target.tagName) || '';
if (tag === 'INPUT' || tag === 'TEXTAREA') return;
if (e.key === ' ') {
// toggle play/pause
e.preventDefault();
btnToggle.click();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
btnSeekBack.click();
} else if (e.key === 'ArrowRight') {
e.preventDefault();
btnSeekFwd.click();
} else if (e.key === 'ArrowUp') {
e.preventDefault();
// increase volume
var v = Math.min(100, parseInt(volume.value, 10) + 5);
volume.value = v;
volume.dispatchEvent(new Event('input'));
} else if (e.key === 'ArrowDown') {
e.preventDefault();
var v2 = Math.max(0, parseInt(volume.value, 10) - 5);
volume.value = v2;
volume.dispatchEvent(new Event('input'));
}
});
// Allow arrow navigation on playlist wrapper (when not focusing items)
playlistEl.addEventListener('keydown', function (e) {
var items = Array.from(playlistEl.querySelectorAll('.playlist-item'));
var focused = document.activeElement;
var idx = items.indexOf(focused);
if (e.key === 'ArrowDown') {
e.preventDefault();
if (idx === -1) { focusPlaylistItem(0); } else focusNextPlaylistItem(idx);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
if (idx === -1) { focusPlaylistItem(playlist.length - 1); } else focusPrevPlaylistItem(idx);
} else if (e.key === 'Home') {
e.preventDefault();
focusPlaylistItem(0);
} else if (e.key === 'End') {
e.preventDefault();
focusPlaylistItem(playlist.length - 1);
}
});
// Initialize
renderPlaylist();
// Focus selection if present
if (selectedIndex >= 0 && playlist.length > 0) setFocusedPlaylistItem(selectedIndex);
// Helper: safe focus if playlist empty
// Minimal protection: avoid throwing if widget isn't available
})();
simple-player.js
// simple-player.js
// - Initializes SC.Widget
// - Adds basic controls (play/pause/load)
// - Integrates with Twilio call events to pause/resume playback
//
// Usage:
// 1) Include <script src="https://w.soundcloud.com/player/api.js"></script> in your page.
// 2) Include Twilio SDK if you use it (optional).
// 3) Include this script after the DOM or at end of body.
// 4) Ensure your iframe has id="sc" (same as simple-player.html example).
(function () {
// Utility: safe DOM ready
function ready(fn) {
if (document.readyState !== 'loading') return fn();
document.addEventListener('DOMContentLoaded', fn);
}
ready(function () {
var iframe = document.getElementById('sc');
if (!iframe) {
console.warn('SoundCloud iframe #sc not found.');
return;
}
// Initialize widget
var widget = null;
try {
widget = SC && SC.Widget && SC.Widget(iframe);
} catch (e) {
console.error('SC.Widget init failed', e);
return;
}
// Wire simple UI actions if present (matches simple-player.html)
var btnPlay = document.getElementById('play');
var btnPause = document.getElementById('pause');
var btnLoad = document.getElementById('load');
var urlInput = document.getElementById('url');
if (btnPlay) btnPlay.addEventListener('click', function () { widget.play(); });
if (btnPause) btnPause.addEventListener('click', function () { widget.pause(); });
if (btnLoad && urlInput) btnLoad.addEventListener('click', function () {
var u = urlInput.value.trim();
if (!u) return alert('Enter a SoundCloud URL');
widget.load(u, { auto_play: true });
});
// Twilio integration: pause/resume logic
var wasPlayingBeforeCall = false;
var resumeButton = null;
function ensureResumeUI() {
if (resumeButton) return;
resumeButton = document.createElement('button');
resumeButton.textContent = 'Resume audio';
Object.assign(resumeButton.style, {
position: 'fixed',
right: '12px',
bottom: '12px',
zIndex: 99999,
background: '#ff5500',
color: '#fff',
border: 'none',
padding: '10px 14px',
borderRadius: '6px',
cursor: 'pointer'
});
resumeButton.addEventListener('click', function () {
widget.play();
removeResumeUI();
});
document.body.appendChild(resumeButton);
}
function removeResumeUI() {
if (!resumeButton) return;
resumeButton.remove();
resumeButton = null;
}
function pauseIfPlaying() {
try {
widget.isPaused(function (paused) {
if (!paused) {
wasPlayingBeforeCall = true;
try { widget.pause(); } catch (e) { console.warn('widget.pause failed', e); }
} else {
wasPlayingBeforeCall = false;
}
});
} catch (e) {
console.warn('pauseIfPlaying error', e);
}
}
function resumeIfNeeded() {
if (!wasPlayingBeforeCall) return;
wasPlayingBeforeCall = false; // clear the remembered state (we will try)
try {
widget.play();
// If browser blocks autoplay, widget may still be paused -> show resume UI
setTimeout(function () {
try {
widget.isPaused(function (paused) {
if (paused) {
ensureResumeUI();
} else {
removeResumeUI();
}
});
} catch (e) {
ensureResumeUI();
}
}, 300);
} catch (err) {
console.warn('widget.play failed', err);
ensureResumeUI();
}
}
// Attach to Twilio Device events if present. Support multiple global shapes.
function attachTwilioHandlers(obj) {
if (!obj) return false;
try {
// Most Twilio Device implementations emit 'connect' / 'disconnect' / 'incoming' / 'error'
if (typeof obj.on === 'function') {
obj.on('connect', pauseIfPlaying);
obj.on('incoming', pauseIfPlaying);
obj.on('disconnect', resumeIfNeeded);
obj.on('cancel', resumeIfNeeded);
obj.on('error', resumeIfNeeded);
console.log('Attached Twilio handlers via .on');
return true;
}
// Some uses expose addEventListener-like API
if (typeof obj.addEventListener === 'function') {
obj.addEventListener('connect', pauseIfPlaying);
obj.addEventListener('incoming', pauseIfPlaying);
obj.addEventListener('disconnect', resumeIfNeeded);
obj.addEventListener('error', resumeIfNeeded);
console.log('Attached Twilio handlers via addEventListener');
return true;
}
} catch (e) {
console.warn('Failed to attach Twilio handlers', e);
}
return false;
}
// Try immediate attachment (common shapes)
var attached = false;
attached = attachTwilioHandlers(window.Device) || attached;
attached = attachTwilioHandlers(window.Twilio && window.Twilio.Device) || attached;
attached = attachTwilioHandlers(window.Twilio) || attached; // sometimes Twilio.Device is nested
// If Twilio not available yet, poll briefly and attach when present
if (!attached) {
var tries = 0;
var maxTries = 20; // ~10 seconds at 500ms interval
var poll = setInterval(function () {
tries++;
attached = attachTwilioHandlers(window.Device) || attached;
attached = attachTwilioHandlers(window.Twilio && window.Twilio.Device) || attached;
attached = attachTwilioHandlers(window.Twilio) || attached;
if (attached || tries >= maxTries) {
clearInterval(poll);
if (!attached) {
console.info('Twilio Device not detected; Twilio integration not attached. If you use a different SDK object, call pauseIfPlaying/resumeIfNeeded from your call lifecycle callbacks.');
}
}
}, 500);
} else {
console.info('Twilio integration attached.');
}
// Expose helpers so other code can call them directly if needed
window.__sc_pauseForCall = pauseIfPlaying;
window.__sc_resumeAfterCall = resumeIfNeeded;
// Optional: when page is unloaded or hidden, remove resume UI
window.addEventListener('pagehide', removeResumeUI);
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'hidden') removeResumeUI();
});
});
})();
style.css
:root{
--max-width: 980px;
--accent: #ff5500;
--muted: #666;
--gap: 12px;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
color-scheme: light;
}
*{box-sizing:border-box}
body{
margin:0;
padding:24px;
background:#fafafa;
color:#111;
display:flex;
justify-content:center;
}
.player-page{
width: min(96vw, var(--max-width));
}
h1,h2{ margin:8px 0; }
.sc-iframe-wrapper{
background:#fff;
border-radius:6px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
overflow:hidden;
}
.widget-container{
margin-top:12px;
}
.controls{
margin-top:10px;
display:flex;
flex-direction:column;
gap: var(--gap);
}
.row{
display:flex;
gap:8px;
align-items:center;
flex-wrap:wrap;
}
button{
background:var(--accent);
color:#fff;
border:none;
padding:8px 12px;
border-radius:6px;
cursor:pointer;
}
button.secondary{
background:#e6e6e6;
color:#111;
}
button:disabled{ opacity:0.6; cursor:default; }
input[type="range"]{
width:160px;
}
input[type="url"]{
flex:1 1 320px;
padding:8px;
border-radius:6px;
border:1px solid #ddd;
}
.note{
margin-top:8px;
color:var(--muted);
font-size:0.95rem;
}
.meta-row{ margin-top:4px; }
.playlist-section{
margin-top:20px;
}
#playlist{
margin:8px 0;
padding:0;
list-style:none;
display:flex;
flex-direction:column;
gap:6px;
max-height:320px;
overflow:auto;
border:1px solid #eee;
padding:8px;
border-radius:6px;
background:#fff;
}
.playlist-item{
display:flex;
justify-content:space-between;
gap:12px;
align-items:center;
padding:8px;
border-radius:6px;
cursor:pointer;
outline: none;
}
.playlist-item[aria-selected="true"]{
background: rgba(255,85,0,0.08);
border:1px solid rgba(255,85,0,0.14);
}
.playlist-item:focus{
box-shadow: 0 0 0 3px rgba(255,85,0,0.12);
}
.hints small{ color:var(--muted); }
@media (max-width:560px){
.controls { gap:8px; }
input[type="range"]{ width:100px; }
}
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>SoundCloud Player (index)</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main class="player-page" id="main" role="main">
<h1>SoundCloud Player</h1>
<!-- Player / Widget -->
<section class="widget-section" aria-labelledby="widget-heading" role="region" aria-label="SoundCloud player">
<h2 id="widget-heading">Player</h2>
<div class="widget-container" id="widget-container">
<div class="sc-iframe-wrapper" aria-hidden="false">
<!-- Replace the `url=` value with your SoundCloud track/playlist URL (URL-encoded) or leave and load via JS -->
<iframe id="sc-widget"
title="SoundCloud Player"
width="100%"
height="166"
scrolling="no"
frameborder="no"
allow="autoplay"
src="https://w.soundcloud.com/player/?url=https%3A//soundcloud.com/forss/flickermood&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false">
</iframe>
</div>
<div class="controls" role="group" aria-label="Player controls">
<div class="row">
<button id="btn-play" aria-label="Play" title="Play">Play</button>
<button id="btn-pause" aria-label="Pause" title="Pause">Pause</button>
<button id="btn-toggle" aria-pressed="false" aria-label="Toggle play/pause" title="Toggle">Toggle</button>
<button id="btn-seek-back" aria-label="Seek back 10 seconds" title="-10s">-10s</button>
<button id="btn-seek-fwd" aria-label="Seek forward 10 seconds" title="+10s">+10s</button>
</div>
<div class="row">
<label for="volume">Volume</label>
<input id="volume" type="range" min="0" max="100" value="80" aria-label="Volume" />
<span id="position" aria-live="polite">00:00 / 00:00</span>
</div>
<div class="row load-row">
<input id="track-url" type="url" placeholder="Paste SoundCloud track/playlist URL" aria-label="Track URL" />
<button id="btn-load" aria-label="Load track" title="Load & Play">Load & Play</button>
</div>
<div class="row meta-row" aria-live="polite">
<strong id="track-title">Title: —</strong>
</div>
<div class="row hints">
<small>Keyboard: while focus is inside player — Space toggles play, ←/→ seek, ↑/↓ volume, Enter loads playlist item.</small>
</div>
</div>
</div>
</section>
<!-- Playlist -->
<section class="playlist-section" aria-labelledby="playlist-heading" role="region" aria-label="Playlist">
<h2 id="playlist-heading">Playlist</h2>
<p class="note">Use arrow keys to navigate the playlist; press Enter to load the focused track.</p>
<ul id="playlist" role="listbox" tabindex="0" aria-label="SoundCloud playlist">
<!-- Items populated by player.js -->
</ul>
<div class="row playlist-actions">
<input id="new-track-url" type="url" placeholder="Add track URL to playlist" aria-label="New track URL" />
<button id="btn-add" aria-label="Add to playlist">Add to Playlist</button>
<button id="btn-clear" aria-label="Clear playlist">Clear Playlist</button>
</div>
</section>
</main>
<!-- SoundCloud widget API (required) -->
<script src="https://w.soundcloud.com/player/api.js"></script>
<!-- Your player logic (the player.js you already have) -->
<script src="player.js"></script>
</body>
</html>
Iframe embed
Single page code (html + css + js) simple-player.html
control soundcloud using js - player.js
simple-player.js
style.css
index.html