Browser-side JS library for controlling YouTube Music.
This was built as part of google-music-webkit, a node-webkit wrapper around YouTube Music. It was forked from [email protected], developed and created by Sajid Anwar and James Fator to make it reusable and well tested.
It is now being maintained by the teams of GPMDP and Radiant Player
ytmusic.js
is not created by, affiliated with, or supported by Google Inc.
playback.getPlaybackTime
renamed toplayback.getCurrentTime
playback.setPlaybackTime
renamed toplayback.setCurrentTime
playback.getSongInfo
renamed toplayback.getCurrentTrack
extras.getSongURL
renamed toextras.getTrackURL
change:song
renamed tochange:track
- Track's now have an
albumArt
prop instead ofart
- New method
getTotalTime
- New method
isPlaying
- ENUMS might have moved a bit due to new bindings
The method toggleRepeat()
no longer accepts arguments and setRepeat(mode)
has replaced its
functionality.
On Thursday May 14, 2015 Google launched a Material redesign of the site. This broke a lot of selectors/functionality. In 3.0.0, we updated our integration to handle those changes. The developer-facing interface has not changed but the underlying system was a breaking change so we decided to make it a major release.
Install the module with: npm install ytmusic
// Load and initialize GMusic
var GMusic = require('ytmusic');
window.gmusic = new GMusic(window);
// Access volume
window.gmusic.volume.getVolume(); // 50 (ranges from 0 to 100)
ytmusic.js
exposes a constructor, GMusic
as its module.exports
(window.GMusic
for
bower
/vanilla).
Constructor for a new Google Music API
gmusic.volume
exposes interfaces to the volume controls of Google Music. Volume can range from 0
to 100 in steps of 5 (e.g. 10, 15, 20).
Retrieve the current volume setting
Returns:
- retVal
Number
- Integer from 0 to 100 representing volume
Change the volume setting
- vol
Number
- Integer to set volume to
Raise the volume by an amount
- amount
Number
- Optional number to raise volume by- For example, if volume is 50 and amount is 5, then the volume will change to 55
- If we exceed 100 when adding new values, volume will stop at 100
- By default, this is 5
Lower the volume by an amount
- amount
Number
- Optional number to lower volume by- For example, if volume is 50 and amount is 5, then the volume will change to 45
- If we exceed 0 when subtracting new values, volume will stop at 0
- By default, this is 5
gmusic.playback
exposes interfaces to the state of music playback and its behavior (e.g.
shuffle).
Retrieve the current progress in a track
Returns:
- retVal
Number
- Integer representing milliseconds from the start of the track
Jump the current track to a time
- milliseconds
Number
- Integer representing milliseconds to jump the current track to
Retrieve the length of the current track
Returns:
- retVal
Number
- Integer representing the length of the track in milliseconds
Determine if a track is current playing
Returns:
- retVal
Boolean
- True if the a track is currently playing, else false
Retrieve current track's metadata
Returns:
- retVal
Track
- Container for track info
Toggle between play and pause for the current track
This will not work if there are no tracks in the queue.
Returns:
- retVal
Number
- Current status of music playback (e.g. 0, 1, 2)- 0 - Playback is stopped
- 1 - Track is paused
- 2 - Track is playing
- Values are available via
GMusic.PlaybackStatus.STOPPED
,GMusic.PlaybackStatus.PAUSED
, andGMusic.PlaybackStatus.PLAYING
Move to the next track
Move to the previous
Retrieve the status of shuffle
Returns:
- retVal
String
- Current state of shuffle (e.g.ALL_SHUFFLE
,NO_SHUFFLE
)ALL_SHUFFLE
will shuffle between all tracksNO_SHUFFLE
will play the tracks in the order they were added- We created constants named
GMusic.ShuffleStatus.ALL_SHUFFLE
orGMusic.ShuffleStatus.NO_SHUFFLE
Set the shuffle mode
- mode
String
- Value to change shuffle to- Valid values are
ALL_SHUFFLE
andNO_SHUFFLE
- Valid values are
Toggle to between shuffle being active or inactive
Retrieve the current setting for repeat
Returns:
- retVal
String
- Current setting for repeat (e.g.LIST_REPEAT
,SINGLE_REPEAT
,NO_REPEAT
)LIST_REPEAT
will repeat the queue when it reaches the last trackSINGLE_REPEAT
will repeat the current track indefinitelyNO_REPEAT
will not repeat the queue- We created constants named
GMusic.RepeatStatus.LIST_REPEAT
,GMusic.RepeatStatus.SINGLE_REPEAT
,GMusic.RepeatStatus.NO_REPEAT
Change the current setting for repeat
- mode
String
- Value to change repeat to- Valid values are
NO_REPEAT
,LIST_REPEAT
,SINGLE_REPEAT
- See
playback.getRepeat()
for meaning
- See
- Valid values are
Toggle through the modes for repeat.
- The order is
NO_REPEAT
,LIST_REPEAT
,SINGLE_REPEAT
Retrieve if the current track is a podcast.
- retVal
Boolean
- True indicates the current track is a podcast.
Moves the current track position thirty seconds ahead.
Moves the current track position 10 seconds back.
Trigger a visualization for the track. This is typically album art.
This is an untested method.
gmusic.rating
exposes interfaces to the rating the current track.
Retrieve the rating for the current track.
Returns:
- retVal
String
- Rating for current track. This varies from 0 to 5- If 0, then there has been no rating
- On a thumbs system, thumbs down is 1 and thumbs up is 5
Switch between thumbs up and no thumbs up for the current track. If thumbs down was set, this will remove the thumbs down rating.
Switch between thumbs down and no thumbs down for the current track. If thumbs up was set, this will remove the thumbs up rating.
Set the rating for the current track
- rating
String
- Rating to set for the current track. This should be between 1 and 5
Removes existing rating from the current track
gmusic.extras
is a collection of utility functions for Google Music
Retrieve the URL of the current track for sharing
This is an untested method
Returns:
- retVal
String
- URL for current track
Hooks are currently bound via .on
and other corresponding methods for
node's EventEmitter
gmusic.on('change:track', function (track) {
});
Triggers when a track changes
gmusic.on('change:track', function (track) {
});
- track
Track
- Same as return value ofplayback.getCurrentTrack()
Triggers when shuffle is toggled
gmusic.on('change:shuffle', function (mode) {
});
- mode
String
- Mode that shuffle changed to- Values are consistent with
playback.getShuffle()
- Values are consistent with
Triggers when repeat is toggled
gmusic.on('change:repeat', function (mode) {
});
- mode
String
- Mode that repeat changed to- Values are consistent with
playback.getRepeat()
- Values are consistent with
Triggers when a track is started, paused, or stopped
gmusic.on('change:playback', function (mode) {
});
- mode
String
- Same as return value ofplayback.getPlaybackState()
Triggers when playback shifts
gmusic.on('change:playback-time', function (playbackInfo) {
});
- playbackInfo
Object
- Container for playback info- current
Number
- Milliseconds of how far a track has progressed - total
Number
- Milliseconds of how long a track is
- current
Triggers when the current track is rated
gmusic.on('change:rating', function (rating) {
});
- rating
Number
- Rating the current track changed to- Consistent with values provided by
rating.getRating()
- Consistent with values provided by
Triggers when switching between listening to music and podcasts
gmusic.on('change:podcast', function (isPodcast) {
});
- isPodcast
Boolean
- Whether a podcast is currently being played- Consistent with values provided by
playback.isPodcast()
- Consistent with values provided by
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for
any new or changed functionality. Lint via npm run lint
and test via npm test
.
Currently, we require a personal Google account exclusively for testing. We will be rating tracks, changing repeat settings, and need predictable track titles. We are using the following tracks (at least 3 required):
Credentials: [email protected] / password
https://musopen.org/music/1333/wolfgang-amadeus-mozart/the-marriage-of-figaro-k-492/
Music cannot be uploaded via webdriver instance nor incognito window
If you don't want to contaminate your personal account, create a new user profile in Chrome.
For exactly one track, set the following via "Edit Info" in Google Music:
Name:
this-is-a-name
Artist:
this-is-an-artist
Album Artist:
this-is-an-album-artist
Album:
this-is-an-album
Composer:
this-is-a-composer
Genre:
this-is-a-genre
Year:
2000
Track #:
1 of 10
Disc #:
3 of 5
Explicit:
Unchecked
Once your Google account is registered and the music is uploaded, set the following environment variables
Once your Google account is registered and the music is uploaded, we are ready to run our test suite:
# Set up Google Music credentials as environment variables
export GOOGLE_MUSIC_JS_EMAIL="[email protected]"
export GOOGLE_MUSIC_JS_PASSWORD="your-google-account-password"
# If you are on Windows, use the following
# set GOOGLE_MUSIC_JS_EMAIL="[email protected]"
# set GOOGLE_MUSIC_JS_PASSWORD="your-google-account-password"
# Install Selenium server files
npm run webdriver-manager-update
# Start up a Selenium server
npm run webdriver-manager-start &
# Run our tests
npm test
# If you are on Windows, please use
# npm run test-windows
Nightly builds are triggered on Travis CI by a third party service service Nightli.es
Finnicky tests can be debugged by a few methods
- Use
describe.only
andit.only
to limit test suite to only run 1 at a time - Use the following script to control
# Enter into the node REPL
node
// Prevent node from exiting via anything but an interrupt
process.exit = function () {};
// Emulate mocha being invoked normally
process.argv = ['node', '_mocha', '--timeout', '10000'];
require('mocha/bin/_mocha');
// Our test suite has written `global.browser` as the last Selenium session
global.browser;
browser;
All files were originally licensed at 5ccfa7b3c7bc5231284f8e42c6a2f2e7fe1e1532
under the MIT
license. This can be viewed its LICENSE.md
. It has been renamed to LICENSE-MIT for ease
of disambiguity.
After this commit, all alterations made by Todd Wolfson and future contributors are released to the Public Domain under the UNLICENSE.