Maestro Migration

This is a guide if you are migrating from Maestro to Vinyl.

For installation instructions and detailed API documentation, please refer to the VINYL_AMZN_USAGE.md guide.

Packages

@amzn/Orchestrajs -> @amzn/vinyl-amzn

API translations:

Creating a Player:

Maestro:

import { Player } from '@amzn/Orchestrajs'

new Player({
    flags: {
        metrics: false, // Metrics true is a dead branch
    },
    appName,
    appVersion,
    oAuthToken,
    customerId,
    deviceId,
    deviceTypeId,
    clientId,
    hostname,
    musicTerritory,
    marketplaceId,
    tier,
    crossDomain,
    withCredentials,
    ipAddress,
    cacheSize: 1, // 3P devices do not support cacheSize > 1. Prefetch tests are separate
})

A Maestro player will create an audio element per cached track.

Vinyl:

import { createVinylAmznPlayer, type Territory } from '@amzn/vinyl-amzn'

const media = new Audio()
media.controls = true
document.body.appendChild(media)

const player = createVinylAmznPlayer({ media })

player.configure({
    dmls: {
        marketplaceId: customerHome.marketplaceId,
        musicTerritory: customerHome.musicTerritory as Territory, // Will be validated
        appMetadata: {
            appId: codeData.app_name!,
            https: true,
            appVersion: codeData.app_version,
        },
        deviceToken: {
            deviceId: codeData.device_serial,
            deviceTypeId: codeData.device_type,
        },
        clientMetadata: {
            clientId: codeData.app_name!,
        },
        host: 'https://music.amazon.com',
        customer: {
            customerId: customerHome.customerId,
            oAuthTokenProvider: () => {
                /* return promise to oAuthToken */
            },
            entitlementList,
        },
    },
})

A Vinyl player is given the single media (audio or video) element. The media element does not need to be on the DOM unless native playback UI is used.

Track Loading / Playing

Maestro:

load preloads a track, but does not activate it. How many tracks you can preload was dependent on the cacheSize configuration. cacheSize can only be 1 for big screen devices.

await player.load('asin://B0157E47K2')

await player.load('https://example.com/myTrack.mp3')

await player.load('coid://d9e4e337-97ba-41a9-9f31-84a8bf99f1dc')

Maestro player.load took optional extra options as a second parameter:

type LoadOptions = {
    isDirectedPlay?: boolean
    isExplicitLanguageFilterOn?: boolean
    isShufflePlay: boolean
    pageType?: any
    selectionSourceType?: any
    selectionSourceId?: any
    selectionSourceSessionId?: any
    bitrates?: any
    position?: number
    explicitId?: string
}

These had no effect for playback except when requesting metrics state.

Maestro had no way of preloading a track from a specific position.

To activate the track and begin playback in Maestro, player.play is used with the same id for loading.

Vinyl:

preload preloads a track but does not activate it. load sets a play queue and activates the first track. See TrackController.preload for more details.

Skyfire WebPlayer if using Vinyl should call preload on a BUFFER action and load then play on a PLAY action.

Load commands for Vinyl take a load configuration. This configuration depends on the track type. Follow the type definition for VinylTrackLoadOptions to see what's supported. Generally this will have the shape:

player.preload({
    type: 'asin',
    uri: 'asin://B0157E47K2',
})

player.preload({
    type: 'src',
    uri: 'https://example.com/myTrack.mp3',
})

player.preload({
    type: 'coid',
    uri: 'coid://d9e4e337-97ba-41a9-9f31-84a8bf99f1dc',
    config: { startTime: 30 },
})

player.load({
    type: 'src',
    uri: 'https://example.com/myTrack.mp3',
}) // Sets the queue to a single track.

Vinyl does have a queue, but it's optional. Calling load with several tracks will play each track one after another and manage preloading the next tracks. When migrating from Maestro, use preload for preloading the next tracks and load with a single track to activate it. Calling load repeatedly replaces the queue.

To begin playback, after calling load to activate the track, call play.

Configuration

Vinyl has dependency configuration when creating the player, the ability to override dependencies, player runtime configuration, and global configuration. Initialization options are provided to Vinyl during createVinylAmznPlayer, global configuration via configureVinylAmznGlobal and runtime configuration via player.configure. The separated structures allows Vinyl to be more modular and give independent systems to define their own configuration.

Maestro has a flat runtime configuration via player.configure.

Vinyl configuration, aside from the DMLS config, can generally be left to their defaults.

Below is a list of Orchestra configuration options and how they would be changed in Vinyl, where applicable.

const player = createVinylAmznPlayer({
    media,
    trackController: { preloadCapacity: 4 },
})
requesterWithRetryRef.set(() => {
    return createRequester({
        retryOptions: RetryStrategy.NO_RETRIES,
    })
})

Playback Controls

A list of Maestro playback controls and the Vinyl counterpart:

Events

To observe Vinyl Events, use const sub = player.on(eventName, handler) Then invoke the returned function to unsubscribe.

Full documentation for using events: EVENTS.md

For full documentation on the events Vinyl emits: VinylPlayerEventMap

A list of Maestro events and the Vinyl counterpart:

Metrics

Maestro did not emit events for metrics, instead it had state that was queried with player.metricsReporter. VinylAmznPlayer instead emits events corresponding to the tier 1 business critical MTS events. To observe these events, use player.metrics.mts.on(...) See the docs for events emitted here: MtsEventMap

These events are not emitted directly to Cirrus, the application is responsible for taking the emitted event from Vinyl and reporting to the required services. Vinyl metrics events have mtsAttributes which are the known MTS attributes that correspond exactly to the lighthouse documentation, and support which provides additional information needed to calculate final values. For example Vinyl cannot calculate initialPlaybackDelay without knowing the timestamp requested by the user to start playback. It therefore provides support attributes describing the time playback started, which can then be used to calculate the final value.