Français, voir plus bas
Source at very end
Since I upgraded to Windows 11, I've had trouble easily casting the songs I want to my Google Nest, to the point that it's annoying me...
Furthermore, I sometimes have to stream games or activities where I clearly need a soundscape in the background.
That's why I'm currently creating as many songs as possible with varied rhythms, but with themes related to my universe, so that viewers can instantly find their way around and say: Ah, this music, we're definitely at Ithara's!!!
Want to listen to them ? Here they go : http://principalityofbastion.org/musiques/
So I asked Claude AI to create a web page that could play all the music I uploaded to a folder, so I could play it, on repeat, randomly.
A few seconds of thought and, he did this for me:
https://www.principalityofbastion.org/musicplayer.html
Feel free to copy the source code for your own use if you want to try modifying it, because it's not perfect. I'll explain below...
I just tested it... I can load songs from the hard drive, I can change the sound, I can navigate through the song, change the music speed, I can configure it to shuffle the songs.
However, as soon as I get to the end of a song, it loads the next one and waits for me to press play again...
Here, however, Claude is having trouble finding a solution...
@deadzy, @invest-time, would you like to test your respective AIs?
You can see the full source code below... for fun if you want, I'll have to wait until tomorrow for the rest.
(FULL SOURCE AT THE END OF THE POST)
Best regards,
≋𝕴𝖙𝖍𝖆𝖗𝖆 𝕲𝖆ï𝖆𝖓≋ Prince of Principality of Bastion
≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋
Discord : https://discord.principalityofbastion.org
Website : https://principalityofbastion.org / https://nft.bastion.city
Social Networks: See on our website.
Founder of the Principality of Bastion
Interact with us by joining our discord, use our #BASTION, or #FR IF you speak french in your post.
Depuis que je suis passé en windows 11, j'ai du mal à caster facilement les chansons que je veux sur mon Google nest, au point que cela m'énervait ...
De plus, je suis parfois obligé de streamer des jeux ou des activités où j'ai clairement besoin d'un univers sonore en arrière plan.
C'est d'ailleurs pour cela que je crée, en ce moment, un maximum de chansons sur des rythmes variés, mais aux thèmes liés à mon univers, pour que les viewers puissent se repérer instantanément en se disant : Ah, cette musique, on est forcément chez Ithara !!!
Envie de les écouter ? Les voici : http://principalityofbastion.org/musiques/
Alors j'ai demandé à Claude IA de me faire une page web pouvant jouer toutes les musiques que je chargerais dans un répertoire, pour pouvoir les lire, en boucle, de façon aléatoire.
Quelques secondes de réflexion et zouh, il m'a fait ceci:
https://www.principalityofbastion.org/musicplayer.html
N'hésitez pas à copier le code source pour votre propre usage si vous voulez tenter de le modifier, car il n'est pas parfait, je vous explique ci-dessous...
Je viens de le tester ... Je peux loader les chansons depuis le disque dur, je peux modifier le son, je peux surfer sur la chanson, changer la vitesse de la musique, je peux faire le setup pour mélanger les chansons.
Par contre dès que j'arrive à la fin d'une chanson, ils charge la suivante et attend qu'on appuie à nouveau sur play...
Là, par contre, claude à du mal me trouve rune solution...
@deadzy , @invest-time auriez-vous envie de tester vos IA respective?
Vous pouvez voir la source complète ci-dessous... pour vous amuser si vous voulez, moi je dois attendre demain pour la suite.
(SOURCE COMPLETE EN FIN DE POST)
Best regards,
≋𝕴𝖙𝖍𝖆𝖗𝖆 𝕲𝖆ï𝖆𝖓≋ Prince of Principality of Bastion
≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋
Discord : https://discord.principalityofbastion.org
Website : https://principalityofbastion.org / https://nft.bastion.city
Social Networks: See on our website.
Founder of the Principality of Bastion
Interact with us by joining our discord, use our #BASTION, or #FR IF you speak french in your post.
language html & JS
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lecteur MP3 Minimaliste</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #1a1a2e, #16213e);
color: #fff;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.player-container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 30px;
max-width: 500px;
width: 100%;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.file-input-container {
margin-bottom: 30px;
text-align: center;
}
.file-input-label {
display: inline-block;
padding: 12px 24px;
background: linear-gradient(45deg, #667eea, #764ba2);
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 1px;
font-size: 12px;
}
.file-input-label:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
#musicFiles {
display: none;
}
.current-track {
text-align: center;
margin-bottom: 20px;
padding: 20px;
background: rgba(255, 255, 255, 0.05);
border-radius: 15px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.track-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 5px;
color: #667eea;
}
.track-info {
font-size: 12px;
opacity: 0.7;
text-transform: uppercase;
letter-spacing: 1px;
}
.audio-player {
width: 100%;
margin-bottom: 20px;
border-radius: 10px;
overflow: hidden;
}
.controls {
display: flex;
justify-content: center;
gap: 15px;
margin-bottom: 20px;
}
.control-btn {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
font-size: 18px;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: scale(1.1);
}
.control-btn:active {
transform: scale(0.95);
}
.progress-container {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 15px;
}
.time {
font-size: 12px;
font-weight: 500;
min-width: 40px;
text-align: center;
}
.progress-bar {
flex: 1;
height: 6px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #667eea, #764ba2);
border-radius: 3px;
width: 0%;
transition: width 0.1s ease;
}
.playlist {
max-height: 200px;
overflow-y: auto;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
padding: 10px;
}
.playlist-item {
padding: 8px 12px;
cursor: pointer;
border-radius: 5px;
transition: all 0.2s ease;
font-size: 14px;
margin-bottom: 2px;
}
.playlist-item:hover {
background: rgba(255, 255, 255, 0.1);
}
.playlist-item.active {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.3), rgba(118, 75, 162, 0.3));
border-left: 3px solid #667eea;
}
.status {
text-align: center;
margin-top: 15px;
font-size: 12px;
opacity: 0.8;
}
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
::-webkit-scrollbar-thumb {
background: rgba(102, 126, 234, 0.5);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(102, 126, 234, 0.7);
}
</style>
</head>
<body>
<div class="player-container">
<div class="file-input-container">
<label for="musicFiles" class="file-input-label">
📁 Chargez vos fichiers MP3
</label>
<input type="file" id="musicFiles" accept="audio/mp3,audio/mpeg" multiple webkitdirectory>
</div>
<div class="current-track">
<div class="track-title">Aucun fichier sélectionné</div>
<div class="track-info">Choisissez un dossier contenant vos MP3</div>
</div>
<audio class="audio-player" controls id="audioPlayer">
Votre navigateur ne supporte pas l'audio HTML5.
</audio>
<div class="controls">
<button class="control-btn" id="prevBtn" title="Précédent">⏮</button>
<button class="control-btn" id="playPauseBtn" title="Lecture/Pause">▶</button>
<button class="control-btn" id="nextBtn" title="Suivant">⏭</button>
<button class="control-btn" id="shuffleBtn" title="Aléatoire">🔀</button>
</div>
<div class="progress-container">
<span class="time" id="currentTime">0:00</span>
<div class="progress-bar" id="progressBar">
<div class="progress-fill" id="progressFill"></div>
</div>
<span class="time" id="duration">0:00</span>
</div>
<div class="playlist" id="playlist"></div>
<div class="status" id="status">🔄 Lecture en boucle activée</div>
</div>
<script>
class MP3Player {
constructor() {
this.audioPlayer = document.getElementById('audioPlayer');
this.playlist = [];
this.currentIndex = 0;
this.isPlaying = false;
this.isShuffled = false;
this.originalPlaylist = [];
this.initializeElements();
this.bindEvents();
}
initializeElements() {
this.playPauseBtn = document.getElementById('playPauseBtn');
this.prevBtn = document.getElementById('prevBtn');
this.nextBtn = document.getElementById('nextBtn');
this.shuffleBtn = document.getElementById('shuffleBtn');
this.progressBar = document.getElementById('progressBar');
this.progressFill = document.getElementById('progressFill');
this.currentTimeEl = document.getElementById('currentTime');
this.durationEl = document.getElementById('duration');
this.playlistEl = document.getElementById('playlist');
this.trackTitle = document.querySelector('.track-title');
this.trackInfo = document.querySelector('.track-info');
this.fileInput = document.getElementById('musicFiles');
}
bindEvents() {
// Contrôles
this.playPauseBtn.addEventListener('click', () => this.togglePlayPause());
this.prevBtn.addEventListener('click', () => this.previousTrack());
this.nextBtn.addEventListener('click', () => this.nextTrack());
this.shuffleBtn.addEventListener('click', () => this.toggleShuffle());
// Barre de progression
this.progressBar.addEventListener('click', (e) => this.seek(e));
// Audio events
this.audioPlayer.addEventListener('loadedmetadata', () => this.updateDuration());
this.audioPlayer.addEventListener('timeupdate', () => this.updateProgress());
this.audioPlayer.addEventListener('ended', () => this.nextTrack());
this.audioPlayer.addEventListener('play', () => this.onPlay());
this.audioPlayer.addEventListener('pause', () => this.onPause());
// Chargement des fichiers
this.fileInput.addEventListener('change', (e) => this.loadFiles(e));
}
loadFiles(event) {
const files = Array.from(event.target.files);
const mp3Files = files.filter(file =>
file.type === 'audio/mp3' || file.type === 'audio/mpeg' || file.name.toLowerCase().endsWith('.mp3')
);
if (mp3Files.length === 0) {
alert('Aucun fichier MP3 trouvé dans le dossier sélectionné.');
return;
}
this.playlist = mp3Files.map((file, index) => ({
file: file,
name: this.extractFileName(file.name),
path: file.webkitRelativePath || file.name,
url: URL.createObjectURL(file),
index: index
}));
this.originalPlaylist = [...this.playlist];
this.currentIndex = 0;
this.renderPlaylist();
this.loadTrack(0);
this.updateTrackInfo();
}
extractFileName(fullPath) {
return fullPath.split('/').pop().replace('.mp3', '');
}
renderPlaylist() {
this.playlistEl.innerHTML = '';
this.playlist.forEach((track, index) => {
const item = document.createElement('div');
item.className = 'playlist-item';
item.textContent = `${track.name}`;
item.addEventListener('click', () => this.playTrack(index));
if (index === this.currentIndex) {
item.classList.add('active');
}
this.playlistEl.appendChild(item);
});
}
loadTrack(index) {
if (index >= 0 && index < this.playlist.length) {
this.currentIndex = index;
this.audioPlayer.src = this.playlist[index].url;
this.updateTrackInfo();
this.updateActivePlaylistItem();
}
}
playTrack(index) {
this.loadTrack(index);
this.play();
}
updateTrackInfo() {
if (this.playlist.length > 0) {
const track = this.playlist[this.currentIndex];
this.trackTitle.textContent = track.name;
this.trackInfo.textContent = `${this.currentIndex + 1} / ${this.playlist.length}`;
}
}
updateActivePlaylistItem() {
const items = this.playlistEl.querySelectorAll('.playlist-item');
items.forEach((item, index) => {
item.classList.toggle('active', index === this.currentIndex);
});
}
togglePlayPause() {
if (this.audioPlayer.paused) {
this.play();
} else {
this.pause();
}
}
play() {
if (this.playlist.length > 0) {
this.audioPlayer.play();
}
}
pause() {
this.audioPlayer.pause();
}
onPlay() {
this.isPlaying = true;
this.playPauseBtn.innerHTML = '⏸';
}
onPause() {
this.isPlaying = false;
this.playPauseBtn.innerHTML = '▶';
}
nextTrack() {
if (this.playlist.length === 0) return;
let nextIndex = this.currentIndex + 1;
if (nextIndex >= this.playlist.length) {
nextIndex = 0; // Boucle au début
}
this.loadTrack(nextIndex);
if (this.isPlaying) {
this.play();
}
}
previousTrack() {
if (this.playlist.length === 0) return;
// Mémoriser si on était en train de jouer
const wasPlaying = !this.audioPlayer.paused;
let prevIndex = this.currentIndex - 1;
if (prevIndex < 0) {
prevIndex = this.playlist.length - 1; // Boucle à la fin
}
this.loadTrack(prevIndex);
// Si on était en train de jouer, continuer la lecture
if (wasPlaying) {
this.shouldAutoPlay = true;
setTimeout(() => {
this.audioPlayer.play().catch(e => {
console.log('Erreur de lecture auto:', e);
});
}, 100);
}
}
toggleShuffle() {
this.isShuffled = !this.isShuffled;
if (this.isShuffled) {
this.shuffleBtn.style.background = 'linear-gradient(45deg, #667eea, #764ba2)';
this.shuffleArray(this.playlist);
} else {
this.shuffleBtn.style.background = 'rgba(255, 255, 255, 0.1)';
this.playlist = [...this.originalPlaylist];
}
this.currentIndex = 0;
this.renderPlaylist();
this.loadTrack(0);
}
shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
seek(event) {
const rect = this.progressBar.getBoundingClientRect();
const percent = (event.clientX - rect.left) / rect.width;
const newTime = percent * this.audioPlayer.duration;
this.audioPlayer.currentTime = newTime;
}
updateProgress() {
if (this.audioPlayer.duration) {
const percent = (this.audioPlayer.currentTime / this.audioPlayer.duration) * 100;
this.progressFill.style.width = percent + '%';
this.currentTimeEl.textContent = this.formatTime(this.audioPlayer.currentTime);
}
}
updateDuration() {
this.durationEl.textContent = this.formatTime(this.audioPlayer.duration);
}
formatTime(seconds) {
if (isNaN(seconds)) return '0:00';
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
}
}
// Initialisation du lecteur
document.addEventListener('DOMContentLoaded', () => {
new MP3Player();
});
</script>
</body>
</html>
Pour l'audio j'utilise VLC, il répond à mes besoins
!DUO
!BBH
You just got DUO from @servelle.
They have 1/1 DUO calls left.
Learn all about DUO here.
certes, mais c'est un soft en plus à lancer et parfois pour le live c'est déjà gourmand en ressources :) Est-ce qu'il permet de caster vers le NEST ???
!LOL
!DUO
You just got DUO from @itharagaian.
They have 1/1 DUO calls left.
Learn all about DUO here.
lolztoken.com
Because they know how to multiply.
Credit: theabsolute
@servelle, I sent you an $LOLZ on behalf of itharagaian
(1/10)
Je ne sais même pas ce qu'est le NEST 😅 mais c'est un open source assez complet je crois
!LOLZ
View more
Bonne soirée
!PIZZA
!LOL
!HUG
journalier
!hivebits
florenceboens, you mined 1.0 🟧 HBIT If you had replied to another Hive user, the HBIT would have been split: 0.9 for you and 0.1 for them as a tip. When you mine HBIT, you're also playing the Wusang: Isle of Blaq game. 🏴☠️ | tools | wallet | discord | community | daily <><
What's more, you found 1.0 ⚪ BLAQ pearl as a bonus treasure token!
Your random number was 0.2917383381934253, also viewable in the Discord server, #hbit-wusang-log channel. Check for bonus treasure tokens by entering your username at block explorer A, explorer B, or take a look at your wallet.
There is a treasure chest of bitcoin sats hidden in Wusang: Isle of Blaq. Happy treasure hunting! 😃 Read about Hivebits (HBIT) or read the story of Wusang: Isle of Blaq.
lolztoken.com
Details are sketchy.
Credit: reddit
@itharagaian, I sent you an $LOLZ on behalf of florenceboens
(3/10)
fini ca amrche
!LOL
lolztoken.com
She still thinks it's going to be a fishpond.
Credit: reddit
@florenceboens, I sent you an $LOLZ on behalf of itharagaian
(3/10)
Delegate Hive Tokens to Farm $LOLZ and earn 110% Rewards. Learn more.
$PIZZA slices delivered:
faustine.books tipped itharagaian
florenceboens tipped itharagaian
@itharagaian(2/20) tipped @seckorama (x2)
isiksenpalvoja tipped itharagaian
Come get MOONed!
Suite des essais demain donc !
!PIZZA
!LOL
!HUG
lolztoken.com
They paint their toenails red and hide in strawberry patches!
Credit: reddit
@itharagaian, I sent you an $LOLZ on behalf of isiksenpalvoja
(2/10)
Farm LOLZ tokens when you Delegate Hive or Hive Tokens.
Click to delegate: 10 - 20 - 50 - 100 HP
non là c'est obn hihi
!LOL
lolztoken.com
Periodically.
Credit: reddit
@isiksenpalvoja, I sent you an $LOLZ on behalf of itharagaian
(4/10)
NEW: Join LOLZ's Daily Earn and Burn Contest and win $LOLZ
Repos jusque demain !
!PIZZA
!LOL
!HUG
lolztoken.com
It was just so lava-able.
Credit: belhaven14
@itharagaian, I sent you an $LOLZ on behalf of faustine.books
(2/10)
Delegate Hive Tokens to Farm $LOLZ and earn 110% Rewards. Learn more.
je tente sa ce weekend
!LOLZ
!HUG
Plus besoin c'est opérationnel :)
IT WORKS, it's LIVE
Ca marche c'est en ligne : http://principalityofbastion.org/mp3.html
It works for me. 👍

I guess the main point of this app should be that someone else can listen to my music and I can listen to theirs :)
Nope, here the goal is simply to make my life easier to play the music for my live sessions :)
To play the music of others, we would need access to their files.
!PIZZA
View more
Delegate your Hive Power to Ecency and
earn daily curation rewards in $Hive!
thank you
!PIZZA