I am currently developing an application that combines Angular and MusicKit to offer users the ability to listen to music simultaneously. However, I encountered a challenging error when trying to run the application using ng serve --host x.x.x.x instead of the default localhost with ng serve:
core.js:14597 ERROR TypeError: Cannot read property 'container' of null
at Player. (musickit.js:formatted:6614)
at musickit.js:formatted:726
at Object.next (musickit.js:formatted:739)
at fulfilled (musickit.js:formatted:627)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
at Object.onInvoke (core.js:16156)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:387)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138)
at zone.js:872
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
21:08:38.100 core.js:14597 ERROR Error: Uncaught (in promise):
TypeError: Cannot read property 'isFairplay' of undefined
TypeError: Cannot read property 'isFairplay' of undefined
at MediaExtension.get [as isFairplay] (musickit.js:formatted:5020)
at musickit.js:formatted:6728
at Array.filter ()
at Player._playbackDataForItem (musickit.js:formatted:6726)
at Player. (musickit.js:formatted:6504)
at musickit.js:formatted:726
The "isFairplay" error may be related to the initial error, but I included it as a precaution. While running on a remote server (ng build, move the dist folder over to /var/www/html) with nginx, the application runs smoothly locally using "ng serve --host x.x.x.x" against my local IP. Everything functions properly when using plain ng serve. I have tested with different Apple Music accounts in various browsers and incognito windows in Chrome.
The goal is to: 1. Display a list of songs from the user's library 2. Allow users to choose a song 3. Subscribe to observable steps: 4. Queue the selected song with musicKit.queueSong 5. Play the queued song using musicKit.player.play()
The errors occur after step 5. Despite adding container.id to the song object, it seems that Apple fails to queue the song correctly. The queuing process returns successfully, indicating other elements in the object might be null or undefined, not just container.id.
The code snippet below demonstrates the above steps. "playSong(..)" is subscribed to in another class:
playSong(songs: any[], index: number): Observable {
if(songs) {
//songs play without the forEach, but musicKit still complains
//about not finding container.id in the song object
songs.forEach(song => song['container'] = { 'id' : song.id });
return from(this.musicKitService.setQueue({ 'items': songs, startPosition: index}))
.pipe(mergeMap(x => this.play()));
}
}
modifyPlayback(arg: Observable): Observable {
return arg.pipe(map(x => this.setTitle()));
}
play(): Observable {
return this.modifyPlayback(from(this.player.play()));
}
The expectation is for the song to start playing in the browser post these actions. Essentially, a single song is being queued and then instructed to play by musicKit.js. However, upon attempting to play the queued song, musicKit.js finds no song available. The mystery lies in what happens to the song after a successful queueing outside of localhost.
In addition, I have posted this issue on the Apple Developer Forums, seeking assistance from others who faced similar problems last year without resolution.
To note, this problem only occurs in Chrome. The code functions correctly in Firefox and mobile Safari.