Hi all, I work in music studio environment.
I’d like to create a before after code to show my service.
Basically the idea is to have two side images, one with title “before” (let’s say the recording status) the other titled “after”(the mixed and mastered status).
I know that is not possible with a slider since is music and cannot work like this but my idea is simpler.
I want that the 2 songs play in synch, so when is clicked on “Before” both the “Before” and “After” songs will be played but the “After” song should be MUTED. So only the “Before” is listenable.
When then is clicked “After”, the “Before” should be MUTED and the "After is listenable.
Maybe the line player should be dragged to start from beginning.
Is it possible?
Could you help me?
Fabio
No velo but you can setup something like this using HTML, CSS, JS - https://wixstudiotemplates.wixstudio.com/car-dealership/blank-3?rc=test-site
2 Likes
That’s wonderful!
How to do that?
use following code in Wix Embed
<div class="container">
<style>
.container {
background: #1a1a1a;
color: #fff;
padding: 2rem;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.player-container {
background: #2a2a2a;
border-radius: 12px;
padding: 2rem;
margin-bottom: 2rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.waveform-container {
margin: 1.5rem 0;
position: relative;
border-radius: 8px;
overflow: hidden;
background: #333;
}
.controls {
display: flex;
align-items: center;
gap: 1rem;
margin-top: 1rem;
}
.play-btn {
background: #4CAF50;
border: none;
color: white;
width: 48px;
height: 48px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s;
}
.play-btn:hover {
background: #45a049;
}
.toggle-container {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
}
.toggle-btn {
flex: 1;
padding: 1rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.toggle-btn.before {
background: #2196F3;
color: white;
}
.toggle-btn.after {
background: #9C27B0;
color: white;
}
.toggle-btn.inactive {
background: #444;
opacity: 0.7;
}
.time-display {
font-family: monospace;
font-size: 1rem;
color: #ddd;
}
</style>
<div class="toggle-container">
<button class="toggle-btn before active" onclick="switchTrack('before')">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/>
<path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/>
</svg>
Before (Raw)
</button>
<button class="toggle-btn after inactive" onclick="switchTrack('after')">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/>
<path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/>
</svg>
After (Mastered)
</button>
</div>
<div class="player-container">
<div id="waveform-before" class="waveform-container"></div>
<div id="waveform-after" class="waveform-container"></div>
<div class="controls">
<button class="play-btn" onclick="togglePlay()">
<svg id="play-icon" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
<path d="M8 5v14l11-7z"/>
</svg>
<svg id="pause-icon" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" style="display: none;">
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
</svg>
</button>
<div class="time-display">
<span id="current-time">0:00</span> / <span id="duration">0:00</span>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/wavesurfer.js/7.7.3/wavesurfer.min.js"></script>
<script>
let activeTrack = 'before';
let isPlaying = false;
const wavesurferBefore = WaveSurfer.create({
container: '#waveform-before',
waveColor: '#4a90e2',
progressColor: '#2196F3',
cursorColor: '#fff',
barWidth: 2,
barGap: 1,
height: 100,
normalize: true,
responsive: true,
});
const wavesurferAfter = WaveSurfer.create({
container: '#waveform-after',
waveColor: '#e91e63',
progressColor: '#9C27B0',
cursorColor: '#fff',
barWidth: 2,
barGap: 1,
height: 100,
normalize: true,
responsive: true,
});
// Load audio files (replace with your URLs)
wavesurferBefore.load('/path/to/your/raw-audio.mp3');
wavesurferAfter.load('/path/to/your/mastered-audio.mp3');
// Sync both players
wavesurferBefore.on('seek', function (progress) {
wavesurferAfter.seekTo(progress);
});
wavesurferAfter.on('seek', function (progress) {
wavesurferBefore.seekTo(progress);
});
function updateTime() {
const currentTime = formatTime(wavesurferBefore.getCurrentTime());
const duration = formatTime(wavesurferBefore.getDuration());
document.getElementById('current-time').textContent = currentTime;
document.getElementById('duration').textContent = duration;
}
function formatTime(seconds) {
seconds = Math.floor(seconds);
const minutes = Math.floor(seconds / 60);
seconds = seconds % 60;
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
wavesurferBefore.on('audioprocess', updateTime);
wavesurferBefore.on('ready', updateTime);
function togglePlay() {
isPlaying = !isPlaying;
document.getElementById('play-icon').style.display = isPlaying ? 'none' : 'block';
document.getElementById('pause-icon').style.display = isPlaying ? 'block' : 'none';
if (isPlaying) {
wavesurferBefore.play();
wavesurferAfter.play();
} else {
wavesurferBefore.pause();
wavesurferAfter.pause();
}
}
function switchTrack(track) {
activeTrack = track;
if (track === 'before') {
wavesurferBefore.setMuted(false);
wavesurferAfter.setMuted(true);
document.querySelector('.toggle-btn.before').classList.remove('inactive');
document.querySelector('.toggle-btn.after').classList.add('inactive');
} else {
wavesurferBefore.setMuted(true);
wavesurferAfter.setMuted(false);
document.querySelector('.toggle-btn.before').classList.add('inactive');
document.querySelector('.toggle-btn.after').classList.remove('inactive');
}
}
// Initial setup
wavesurferAfter.setMuted(true);
// Handle ready states
let beforeReady = false;
let afterReady = false;
wavesurferBefore.on('ready', () => {
beforeReady = true;
if (afterReady) enableControls();
});
wavesurferAfter.on('ready', () => {
afterReady = true;
if (beforeReady) enableControls();
});
function enableControls() {
document.querySelector('.play-btn').disabled = false;
updateTime();
}
</script>
Place the before and after audio link in following code(you can get URL from media manage in wix
wavesurferBefore.load('/path/to/your/raw-audio.mp3');
wavesurferAfter.load('/path/to/your/mastered-audio.mp3');
1 Like
That’s very cool, is quite like what I was looking for but is ok for only 1 song displayed, and would keep too space on the visualization, could you change a bit to make more for a playlist?
So one only main toggle to switch between raw and mastered, and all the song one after the other like following image?