i have been on this problem for a while, haven’t figured a way around it, i was actually building this audio player website and everything seems working well except from the audio player itself, after fetching the resources from my spring boot api, i cant initialize each resource with its specific information, when i click the play button on one resource, the slider moves for all resource… this is a screenshot of my site to get a better understanding…
This is when the page is first loaded, the slider is not initialized to 0.00 which is the start position, and when i play a resource, i get this…
So i got this code online, but the code was made for just one resource, so i was trying to see how i can get it to work for multiple resource but am out of luck, this is my .html code…
<ng-container *ngIf="appState.appData.data.beats['content'].length > 0">
<div class="row car-filter">
<div class="col-lg-3 col-md-4 col-sm-6 mix"
*ngFor="let beat of appState.appData.data.beats['content']; let i=index">
<div class="car__item card" style="background-color: black;">
<div class="card-body" style="padding: 0;" >
<div class="car__item__pic__slider">
<img [src]='clientApiUrl+"/"+beat?.artWork' alt="artwork"
style="max-width: 300px; border:0;position: relative; object-fit: cover;" height="169px">
<button class="btn shadow-md"
style="position:absolute;left:0; border-radius: 100%;top: 25%;width:100%;" (click)="playStream(clientApiUrl+'/'+beat?.uri)" [disabled]="state?.error">
<i class="fa fa-3x shadow-md fa-play-circle" *ngIf="!(playing$ | async)" style="color: #d5eebb"></i>
<i class="fa fa-3x shadow-md fa-pause-circle" *ngIf="(playing$ | async)" style="color: #5f7a61;"></i>
</button>
</div>
<div style="margin: 0; padding: 4px 8px; color: white;">
<div class="song-slider">
<input type="range" min="0" [max]="state?.duration" step="0.01" [value]="state?.currentTime" (input)="onSliderChangeEnd($event)" [disabled]="state?.error" class="seek-bar">
<div class="d-flex justify-content-between align-items-center">
<span class="current-time">{{ state?.readableCurrentTime }}</span>
<span class="song-duration">{{ state?.readableDuration }}</span>
</div>
</div>
</div>
<div class="card-details">
<p class="card-text">{{ beat?.name }}</p>
<small style="color: silver; font-size: 10px;">{{ beat?.genre.name}}</small>
| <small style="color: silver; font-size: 10px;">{{
beat?.mood.name}}</small>
| <small style="color: silver; font-size: 10px;">{{
beat?.beatKey.name}}</small>
</div>
<div id="cartbtns">
<div class="row">
<div class="col-md-6 mp3btn">
<button class="btn btn-block" (click)="addToCart(beat, 'MP3')"
style="background-color: #5cfe34;border-radius: 0%; position: relative;">
<i class="fa fa-shopping-cart"
style="font-size: 15px; color: gray;"></i>
<span
style="color: white; font-weight: 500; font-size: 12px;">${{beat?.priceMp3.toFixed(2)}}</span>
<sup style="position:absolute;right:0;top: 6px;">
<span class="label label-info"
style="font-size: 9px; border-color: lightgrey; color: white;padding: 2px;">mp3</span>
</sup>
</button>
</div>
<div class="col-md-6 wavbtn">
<button class="btn btn-block" (click)="addToCart(beat, 'WAV')"
style="background-color: #221F1F;border-radius: 0%;position: relative;">
<i class="fa fa-shopping-cart"
style="font-size: 15px; color: gray;"></i>
<span
style="color: white; font-weight: 500; font-size: 12px;">${{beat?.priceWav.toFixed(2)}}</span>
<sup style="position:absolute;right:0;top: 6px;">
<span class="label label-warning"
style="font-size: 9px;border-color: lightgrey; color: white; padding: 2px;">wav</span>
</sup>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row align-items-center justify-content-center mt-2">
<div class="align-self-baseline pt-2 col-md-12 text-center">
<a class="btn btn-light btn-xl js-scroll-trigger text-uppercase" href="beats">Check Out
More</a>
</div>
</div>
</ng-container>
and the .ts file for this component…
playing: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
playing$ = this.playing.asObservable();
files: Array<any> = [];
state :StreamState;
state$ = this.audioService.getState();
currentTime: BehaviorSubject<string> = new BehaviorSubject<string>('00.00');
currentTime$ = this.currentTime.asObservable();
constructor(private beatService: BeatServiceService,
private cartService: CartServiceService,
private toastrService: ToastrService,
private router: Router, private audioService: AudioService) {
this.cartItem = new CartItem();
this.search = '';
this.sortBy = "id";
this.page = 0;
this.audioService.getState().subscribe(state => {
this.state = state;
});
}
ngOnInit(): void {
}
playStream(url) {
this.audioService.playStream(url).subscribe(events => {
this.playing.next(true);
});
}
pause() {
this.audioService.pause();
}
play() {
this.audioService.play();
}
stop() {
this.audioService.stop();
}
onSliderChangeEnd(change) {
this.audioService.seekTo(change.value);
}
And my audio-service.ts is…
export class AudioService {
private date: Date;
private stop$ = new Subject();
private audioObj = new Audio();
beat: Beat;
private readonly adminApiServerUrl = environment.apiBaseUrl.admin;
clientApiServerUrl = environment.apiBaseUrl.client;
private state: StreamState = {
playing: false,
readableCurrentTime: '',
readableDuration: '',
duration: undefined,
currentTime: undefined,
canplay: false,
error: false,
};
stateChange: BehaviorSubject<StreamState> = new BehaviorSubject(this.state);
private resetState() {
this.state = {
playing: false,
readableCurrentTime: '',
readableDuration: '',
duration: undefined,
currentTime: undefined,
canplay: false,
error: false
};
}
getState(): Observable<StreamState> {
return this.stateChange.asObservable();
}
private updateStateEvents(event: Event): void {
switch (event.type) {
case "canplay":
this.state.duration = this.audioObj.duration;
this.state.readableDuration = this.formatTime(this.state.duration);
this.state.canplay = true;
break;
case "playing":
this.state.playing = true;
break;
case "pause":
this.state.playing = false;
break;
case "timeupdate":
this.state.currentTime = this.audioObj.currentTime;
this.state.readableCurrentTime = this.formatTime(
this.state.currentTime
);
break;
case "error":
this.resetState();
this.state.error = true;
break;
}
this.stateChange.next(this.state);
}
constructor() { }
audioEvents = [
"ended",
"error",
"play",
"playing",
"pause",
"timeupdate",
"canplay",
"loadedmetadata",
"loadstart"
];
private streamObservable(url: string) {
return new Observable(observer => {
// Play audio
this.audioObj.src = url;
this.audioObj.load();
this.audioObj.play();
const handler = (event: Event) => {
this.updateStateEvents(event);
observer.next(event);
};
this.addEvents(this.audioObj, this.audioEvents, handler);
return () => {
// Stop Playing
this.audioObj.pause();
this.audioObj.currentTime = 0;
// remove event listeners
this.removeEvents(this.audioObj, this.audioEvents, handler);
// reset state
this.resetState();
};
});
}
private addEvents(obj, events, handler) {
events.forEach(event => {
obj.addEventListener(event, handler);
});
}
private removeEvents(obj, events, handler) {
events.forEach(event => {
obj.removeEventListener(event, handler);
});
}
playStream(url) {
return this.streamObservable(url).pipe(takeUntil(this.stop$));
}
play() {
this.audioObj.play();
}
pause() {
this.audioObj.pause();
}
stop() {
this.stop$.next();
}
seekTo(seconds) {
this.audioObj.currentTime = seconds;
}
formatTime(time: number, format: string = "HH:mm:ss") {
const momentTime = time * 1000;
return moment.utc(momentTime).format(format);
}
}
I will really appreciate i can get assisted with this, i know the codes are really lengthy but i didnt want to leave anything out, thank you all…