- Notifications
You must be signed in to change notification settings - Fork 26
Description
Hi! I'm trying to build quite a complex audio platform and after days of looking for the right audio player, I think cassette might be the one I need. But I kinda stuck here and before I go deeper and start reinventing the wheels, I thought, I better ask for advice and guidance, and if available examples :)
So, I'm trying the get multiple audio players per page and one footer "main player", all the players will be customized and display waveforms (which I render serverside). Here is a simple example (even though here the footer player has just simple progress bar in my case it would have also a waveform)

From all the Cassette examples I see, that usually if there are multiple players per page - they are just simple play buttons without displaying the audio duration and so on. Can it be changed so every file has duration and progress and all the details?
I found this demo app https://github.com/benwiley4000/cassette-demo-app and tried to modify it's code a bit, to achieve what I'm looking for but unfortunately, I cannot get it to work right, even though I managed to attach a ProgressBar to the players I'm not sure how to give them unique ID or other RIGHT way of doing it, so when we change the progress of the main player the progress should also be changed only for the currently playing player in the playlist. Here is the screenshot and the code I managed to "compose":

import React, { Component } from 'react';
import './App.css';
import {
PlayerContextProvider,
FullscreenContextProvider,
playerContextFilter,
PlayerContextGroup
} from '@cassette/core';
import { MediaPlayerControls } from '@cassette/player';
import { MediaProgressBar } from '@cassette/components';
import './player_styles.scss';
import playlist from './playlist';
function TrackPosition({ activeTrackIndex, playlist }) {
return (
<div
style={{
fontSize: '1rem',
display: 'flex',
alignItems: 'center',
fontWeight: 'bold'
}}
>
Track {activeTrackIndex + 1} / {playlist.length}
);
}
function PlaylistMenu({ playlist, activeTrackIndex, onSelectTrackIndex }) {
return (
<div
style={{
width: '280px',
marginTop: '2rem',
marginBottom: '2rem',
fontSize: '1.2rem'
}}
>
Select a track:
{playlist.map((track, i) => {
const playing = activeTrackIndex === i;
TrackPosition({activeTrackIndex, playlist});
return ( <div key={i} style={{ fontWeight: playing ? 'bold': undefined, margin: '0.5rem', padding: '0.5rem', borderRadius: '0.25rem', border: '2px solid white', cursor: 'pointer', textAlign: 'left', marginBottom: '2rem' }} onClick={() => onSelectTrackIndex(i)} > {playing && '▶️'} <i>{track.artist}</i> - {track.title} <MediaProgressBar style={{ background: 'black', height: 15 }} progressStyle={{ background: 'orange' }} progressDirection="right" /> </div> ); })} </div> );
}
PlaylistMenu = playerContextFilter(PlaylistMenu, [
'playlist',
'activeTrackIndex',
'onSelectTrackIndex'
]);
function FfwButton({ playbackRate, onSetPlaybackRate }) {
return (
<div
style={{
fontSize: '2rem',
display: 'flex',
alignItems: 'center',
fontWeight: 'bold',
WebkitUserSelect: 'none',
MozUserSelect: 'none',
msUserSelect: 'none',
userSelect: 'none',
WebkitTouchCallout: 'none'
}}
onTouchStart={() => onSetPlaybackRate(3)}
onMouseDown={() => onSetPlaybackRate(3)}
onMouseUp={() => onSetPlaybackRate(1)}
onMouseLeave={() => onSetPlaybackRate(1)}
onTouchEnd={() => onSetPlaybackRate(1)}
>
⏩
);
}
FfwButton = playerContextFilter(FfwButton, [
'playbackRate',
'onSetPlaybackRate'
]);
const secondPlaylist = [
{
url:
'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
title: 'Elephants Dream',
artist: 'Orange Open Movie Project'
}
];
class Player extends Component {
render() {
return (
<div className="App" style={{ background: 'navy' }}>
<PlayerContextProvider
playlist={playlist}
initialStateSnapshot={this.snapshot}
onStateSnapshot={shot => {
localStorage.setItem('media_snapshot', JSON.stringify(shot));
}}
>
<div
className="media_player_container"
ref={elem => this.mediaContainerElem = elem}
>
<MediaPlayerControls
controls={[
'spacer',
'playpause',
'forwardskip',
'mute',
'spacer',
'progress',
'fullscreen'
]}
/>
{this.state}
);
}
}
export default Player;
Thanks a lot for reading through this!
P.S. on the docs website we got this "main" footer player, how do we actually build such kind of footer player? I cannot find examples of this. But from what I understand it's just a simple player which is fixed to the bottom of the page with css?