[GH-ISSUE #935] Chromecast Backend - Working Proposal #602

Open
opened 2026-02-26 02:33:40 +03:00 by kerem · 7 comments
Owner

Originally created by @kellertobias on GitHub (Mar 17, 2019).
Original GitHub issue: https://github.com/koel/koel/issues/935

Hey guys.
I have written a simple Chromecast Backend for Koel (At the moment, there is no UI for that).
The backend requires to run in the same network as the chromecast (as the Streaming ocntrol happens via mDNS).

The application logs in to the Koel api and fetches the playlists. Then you can select one playlist to play. The playback will loop the given playback on the given chromecast.

https://gist.github.com/kellertobias/66825b25e7f3435aec5f09255caa3c6a

Would be cool if something like that could be part of the main application.

Originally created by @kellertobias on GitHub (Mar 17, 2019). Original GitHub issue: https://github.com/koel/koel/issues/935 Hey guys. I have written a simple Chromecast Backend for Koel (At the moment, there is no UI for that). The backend requires to run in the same network as the chromecast (as the Streaming ocntrol happens via mDNS). The application logs in to the Koel api and fetches the playlists. Then you can select one playlist to play. The playback will loop the given playback on the given chromecast. https://gist.github.com/kellertobias/66825b25e7f3435aec5f09255caa3c6a Would be cool if something like that could be part of the main application.
Author
Owner

@kellertobias commented on GitHub (Mar 29, 2019):

I now have written a simple library that is able to queue a list of songs in a playback queue for chromecast. I am trying to integrate it with koel.

<!-- gh-comment-id:478164223 --> @kellertobias commented on GitHub (Mar 29, 2019): I now have written a simple library that is able to queue a list of songs in a playback queue for chromecast. I am trying to integrate it with koel.
Author
Owner

@kellertobias commented on GitHub (Mar 30, 2019):

@phanan I've finished my chromecast implementation. It is based on the last release (v3.7.2) and can't do all the things koel can do; but you can shuffle a playlist, play, pause, next and prev. And it shows which song is currently playing. And because I use the google queue instead of the koel queue, you can also close the browser window while playing.

It is client only and my code is kind of hacky (I am usually writing react with coffeescript and am not familiar with vue), but works. As it uses the default media receiver in the chromecast, you dont need a google developer account and you also can do multi room audio with it out of the box.

I have written a wrapper around the most critical chromecast functions. Check out http://cc.music.kellertobi.de/js/sender.js (or http://cc.music.kellertobi.de/source/sender.coffee for the source).

after Initializing the cast framework and loading the player, you can use it

(in the index.html)

<script src="https://cc.music.kellertobi.de/js/sender.js"></script>
    <script type="text/javascript">
        window.castPlayer = new CastPlayer();
        window['__onGCastApiAvailable'] = function(isAvailable) {
          if (isAvailable) {
            window.castPlayer.initializeCastApi();
          }
        };
    </script>
    <script src="https://cc.music.kellertobi.de/koel/public/js/app.js"></script>
    <script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

In the vue code, I basically have done the following:

  • In the components/shared/song-list-controls.vue: Add a button that triggers the cast-dialog by calling castPlayer.connect()
  • In components/site-footer/index.vue, I added in the created method some code that registers an update handler (see Update Handler below) - dont forget to import config
  • last but not least: in services/playback.js I hooked every function that handles the queue (pause, resume, playNext, etc) to call the castPlayer method if the cast is casting
  • and also in playback.js I hooked the command that plays a queue (see hook queue below)

Update Handler (sorry for the bad code style; Have written this while learning vue, struggling with JS (vs Coffee) and f**ing with the chromecast api)

console.log("index.vue:init")
    var currentSong = null, lastSongId = null, lastSongState = null
    castPlayer.registerUpdateHandler(({status, song, volume}) => {
      var songId = song.url
      if(songId) {
        songId = songId.split('api/')
        songId = songId[1]
        songId = songId.split('/play')
        songId = songId[0]
        if (!currentSong || songId != lastSongId) {
          currentSong = songStore.byId(songId)
          console.log("HANDLER - Looking for Song", songId, currentSong)
        }

        if(status == "PLAYING" || status == 'BUFFERING') {
          currentSong.playbackState = 'playing'
        } else {
          currentSong.playbackState = 'stopped'
        }

        if(
          currentSong && (
            lastSongState != currentSong.playbackState ||
            lastSongId != songId
          )
        ) {
          console.log("HANDLER - Status Changed", songId, currentSong)
          event.emit('song:played', currentSong)
          document.title = `${currentSong.title} ♫ ${config.appTitle}`
        }
        if (currentSong) {
          lastSongState = currentSong.playbackState
        } else {
          lastSongState = null
        }
        lastSongId = songId
      } 
    })

hook queue (add before the Vue.nextTick)

    if (castPlayer.isCasting()) {
      console.log("Playlist -> castPlaylist Caught")
      var queue = songs.map(function(song) {
        return {
          url: songStore.getSourceUrl(song),
          title: song.title,
          artist: song.artist.name,
          album: song.album.name,
          cover: song.album.cover
        }
      })

      castPlayer.enqueue(queue)
      return
    }
<!-- gh-comment-id:478203719 --> @kellertobias commented on GitHub (Mar 30, 2019): @phanan I've finished my chromecast implementation. It is based on the last release (v3.7.2) and can't do all the things koel can do; but you can shuffle a playlist, play, pause, next and prev. And it shows which song is currently playing. And because I use the google queue instead of the koel queue, you can also close the browser window while playing. It is client only and my code is kind of hacky (I am usually writing react with coffeescript and am not familiar with vue), but works. As it uses the default media receiver in the chromecast, you dont need a google developer account and you also can do multi room audio with it out of the box. I have written a wrapper around the most critical chromecast functions. Check out http://cc.music.kellertobi.de/js/sender.js (or http://cc.music.kellertobi.de/source/sender.coffee for the source). after Initializing the cast framework and loading the player, you can use it (in the index.html) ``` <script src="https://cc.music.kellertobi.de/js/sender.js"></script> <script type="text/javascript"> window.castPlayer = new CastPlayer(); window['__onGCastApiAvailable'] = function(isAvailable) { if (isAvailable) { window.castPlayer.initializeCastApi(); } }; </script> <script src="https://cc.music.kellertobi.de/koel/public/js/app.js"></script> <script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script> ``` In the vue code, I basically have done the following: - In the `components/shared/song-list-controls.vue`: Add a button that triggers the cast-dialog by calling `castPlayer.connect()` - In `components/site-footer/index.vue`, I added in the `created` method some code that registers an update handler (see Update Handler below) - dont forget to import config - last but not least: in `services/playback.js` I hooked every function that handles the queue (pause, resume, playNext, etc) to call the castPlayer method if the cast is casting - and also in `playback.js` I hooked the command that plays a queue (see hook queue below) Update Handler (sorry for the bad code style; Have written this while learning vue, struggling with JS (vs Coffee) and f**ing with the chromecast api) ``` console.log("index.vue:init") var currentSong = null, lastSongId = null, lastSongState = null castPlayer.registerUpdateHandler(({status, song, volume}) => { var songId = song.url if(songId) { songId = songId.split('api/') songId = songId[1] songId = songId.split('/play') songId = songId[0] if (!currentSong || songId != lastSongId) { currentSong = songStore.byId(songId) console.log("HANDLER - Looking for Song", songId, currentSong) } if(status == "PLAYING" || status == 'BUFFERING') { currentSong.playbackState = 'playing' } else { currentSong.playbackState = 'stopped' } if( currentSong && ( lastSongState != currentSong.playbackState || lastSongId != songId ) ) { console.log("HANDLER - Status Changed", songId, currentSong) event.emit('song:played', currentSong) document.title = `${currentSong.title} ♫ ${config.appTitle}` } if (currentSong) { lastSongState = currentSong.playbackState } else { lastSongState = null } lastSongId = songId } }) ``` hook queue (add before the Vue.nextTick) ``` if (castPlayer.isCasting()) { console.log("Playlist -> castPlaylist Caught") var queue = songs.map(function(song) { return { url: songStore.getSourceUrl(song), title: song.title, artist: song.artist.name, album: song.album.name, cover: song.album.cover } }) castPlayer.enqueue(queue) return } ```
Author
Owner

@phanan commented on GitHub (Apr 7, 2019):

@kellertobias Thanks for the great work! Unfortunately I'm not familiar with Chromecast and its development, so I'm afraid I won't be able to provide any feedback. I'm leaving this issue open though, so that whoever interested in the topic can join force :)

<!-- gh-comment-id:480588061 --> @phanan commented on GitHub (Apr 7, 2019): @kellertobias Thanks for the great work! Unfortunately I'm not familiar with Chromecast and its development, so I'm afraid I won't be able to provide any feedback. I'm leaving this issue open though, so that whoever interested in the topic can join force :)
Author
Owner

@warpdesign commented on GitHub (Jan 21, 2022):

I stumbled upon this issue and am wondering what's missing to make a PR to add Chromecast support to Koel?

@kellertobias Do you have a branch with your code changes? (your sender links appear to be broken

<!-- gh-comment-id:1018617720 --> @warpdesign commented on GitHub (Jan 21, 2022): I stumbled upon this issue and am wondering what's missing to make a PR to add Chromecast support to Koel? @kellertobias Do you have a branch with your code changes? (your sender [links](http://cc.music.kellertobi.de/js/sender.js) appear to be broken
Author
Owner

@kellertobias commented on GitHub (Jan 21, 2022):

nope. using Apple Music in the meantime.

<!-- gh-comment-id:1018629878 --> @kellertobias commented on GitHub (Jan 21, 2022): nope. using Apple Music in the meantime.
Author
Owner

@warpdesign commented on GitHub (Jan 21, 2022):

nope. using Apple Music in the meantime.

That's too bad. Would you have some source code left somewhere so that I don't have to restart from scratch?

<!-- gh-comment-id:1018635283 --> @warpdesign commented on GitHub (Jan 21, 2022): > nope. using Apple Music in the meantime. That's too bad. Would you have some source code left somewhere so that I don't have to restart from scratch?
Author
Owner

@kellertobias commented on GitHub (Jan 21, 2022):

Nope. I have changed my git server twice in the meantime and that is an old project that never went with.

<!-- gh-comment-id:1018658127 --> @kellertobias commented on GitHub (Jan 21, 2022): Nope. I have changed my git server twice in the meantime and that is an old project that never went with.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/koel-koel#602
No description provided.