Migrate Web SDK

Use this guide to migrate your Player Web SDK from AMP1 to AMP2.

The guide lists specific player features and functions, their AMP1 implementation, and how you should implement them in AMP2 for successful migration.
Review Comprehensive coverage analysis for a summary of AMP1 vs. AMP2 coverage for API methods, events, and features. For a detailed feature and function mapping with examples, see the following tables:

Additional reference:

1. Get started with basic integration changes

Player script tag

AMP can be embedded using a CDN-hosted model or self-hosted model. Compare implementation of the player script tags for AMP1 and AMP2.

  • CDN-hosted script

AMP1 implementation:

<html>
  <head>
    <script src="https://amp.akamaized.net/hosted/1.1/player.esi?apikey=MY_API_KEY&version=9.1.36"></script>
  </head>
  <body>
  </body>
</html>

AMP2 implementation (development):

<html>
  <head>
<script src="https://cdn.bitmovin.com/player/web/8/bitmovinplayer.js" type="text/javascript"></script>
  </head>
  <body>
  </body>
</html>
  • Self-hosted script

AMP1 implementation:

<html>
  <head>
    <script src="akamai/amp/core/amp.js"></script>
  </head>
  <body>
  </body>
</html>

AMP2 implementation (production):

For the production version, it is recommended to use self-hosting. The web integration option is available using the NPM package .

NPM package

AMP1 implementation:

npm install adaptive-media-player
// Import player module 
import  AMP  from  'adaptive-media-player'

AMP2 implementation:

npm install bitmovin-player
// Import player modules in the correct order 
import { Player, PlayerEvent } from 'bitmovin-player/modules/bitmovinplayer-core';
import EngineBitmovinModule from 'bitmovin-player/modules/bitmovinplayer-engine-bitmovin';
import MseRendererModule from 'bitmovin-player/modules/bitmovinplayer-mserenderer';

Initialize the player

AMP1 implementation:

// Include player script 
// Define empty DIV for player
// Define config object
// Instantiate player
akamai.amp.AMP.create("amp", config)
  .then(function (player) {
    console.log("AMP Player ready");
  });

AMP2 implementation:

// Include player script
// Define empty DIV for player
// Define config object
// Instantiate player (new())
// Load Media into player
var player = new bitmovin.player.Player(document.getElementById("container-id"), config);

2. Migrate player configurations

Stream URL configuration

AMP1 implementation:

media: {
  source: [{
    src: "https://akamtrans-a.akamaihd.net/delivery/20/35/2035ef57-5cac.m3u8",
    type: "application/x-mpegURL"
  }]
}

AMP2 implementation:

const source = {
  title: 'Art of Motion',
  hls: 'https://akamtrans-a.akamaihd.net/delivery/20/35/2035ef57-5cac.m3u8'
};

player.load(source);

Autoplay configuration

AMP1 implementation:

{
  autoplay: true,
  autoplayPolicy: "muted"
}

AMP2 implementation:

playback: {
  autoplay: true,
  muted: true
}

Low Latency configuration

AMP1 implementation:

  • For HLS:
    {
     hls: {
     	data: {
       		lowLatencyMode: true,
    			liveMaxLatencyDuration: 4,
     	}
    }
    
  • For Dash:
    dash: {
     	settings: {
       		streaming: {
    			lowLatencyEnabled: true,
    			delay: {
    					liveDelay: 4
    			},
    		}
     	}
    }
    

AMP2 implementation:

Supporting both HLS and Dash:

const config = new util.PlayerConfigBuilder("MY-PLAYER-KEY")
  .enableLowLatency({ targetLatency: 4 })
  .build();

User settings configuration

The player stores a user's preferences in the browser's local storage, so AMP remembers and applies them across sessions for user convenience and more personalized playback experience.

AMP1 implementation:

settings: {
		defaults: {
			captions: {
				visible: true,
				fontFamily: "monospacedSerif",
				fontSize: "large",
				fontColor: "white",
				fontOpacity: "100%",
				edgeType: "rightShadow",
				edgeColor: "black",
				edgeOpacity: "50%"
				backgroundColor: "black",
				backgroundOpacity: "50%",
				windowColor: "black",
				windowOpacity: "50%",
				scroll: "popout"
			}
		}
	}

AMP2 implementation:

Check with a Bitmovin representative for options to configure user preferences.

3. Perform playback fine tuning

Fast playback startup

To improve playback startup time, start playback at a lower resolution irrespective of the user’s bandwidth capabilities.

AMP1 implementation:

 const config = {
		autoplay: true,
		autoplayPolicy: "muted",
		hls: {
			quality: {
					startLevel: 0 // use the lowest rendition available
			}
		}
	}

AMP2 implementation:

{
    key: 'USER_PLAYER_LICENSE_KEY',
    playback: {
        autoplay: false,
        muted: false
          },
    adaptation: {
        startupBitrate: "4000kbps",
        maxStartupBitrate: "7mbps", //ignored if startupBitrate defined
        }
}

Playback Bitrate Ceiling

In some cases, you may want to limit the player's maximum ABR quality level. You can configure a ceiling to avoid playback at higher bitrates when they aren't required, reducing unnecessary resource usage.

AMP1 implementation:

    const config = {
		autoplay: true,
		autoplayPolicy: "muted",
		hls: {
			maxBitrate: 500000 // 0.5 Mbps
		}
	}

AMP2 implementation:

{
    key: 'USER_PLAYER_LICENSE_KEY',
    playback: {
        autoplay: false,
        muted: false
          },
    adaptation: {
        bitrates: {
            maxSelectableVideoBitrate: "0.5mbps",
            minSelectedVideoBitrate: 0,
         },
     }
}

4. Migrate advanced features

Use this information and examples to migrate advanced features for your player.

Player transforms

AMP1 transformAMP2 eventMigration notesCode example
adbreakonAdsManagerAvailableCoult integrate accessing IMA’s ad managerSee Ad break transforms
adrequestN/ACould integrate with preprocessHttpRequestSee Ad request transforms
cuechangecueenter, cueupdateDirect mappingplayer.on(‘cueenter’, callback)
errorerrorDirect mappingplayer.on(‘error’, callback)
mediamediaCould integrate with preprocessHttpRequestSee Media transforms

📘

See Event mapping for Web SDK for a complete list of AMP1 vs. AMP2 event mapping.

Media transforms

AMP1: Just-in-time changes to media source object or URLs.

player.addTransform('media', function(media) {
  media.src += '?token=' + getToken();
  return media;
});

AMP2: Use Network API for HTTP request/response manipulation.

player.network.preprocessHttpRequest = function(type, request) {
  if (type === player.network.HttpRequestType.MEDIA) {
    request.url += '?token=' + getToken();
  }
  return Promise.resolve(request);
};

Ad request transforms

AMP1: Just-in-time changes to ad request object or URLs, before an ad client request to the ad server.

player.addTransform(akamai.amp.TransformType.AD_REQUEST, function (ad) {
    ad.request.setAdWillAutoPlay(false)
       ad.request.setAdWillPlayMuted(true)
       ad.request.adTagUrl += "&testing=123456"

   return ad;
});

AMP2: Use Network API for HTTP request/response manipulation.

player.network.preprocessHttpRequest = function(type, request) {
  if (type === player.network.HttpRequestType.MANIFEST_ADS) {
    adrequest.url += '?cust_params=' + getAdParams();
  }
  return Promise.resolve(request);
};

Ad break transforms

AMP1: Just-in-time changes after the ad request is made and break is ready to play.

akamai.amp.AMP.create("akamai-media-player", config, function (event) {
                   amp = event.player
                   // skip prerolls
                   amp.addTransform(akamai.amp.TransformType.AD_BREAK, function (adbreak) {
                       if (adbreak.type === "preroll" || adbreak.type == "postroll") {
                           return; // return a null value to skip the ad break
                       }
                       return adbreak;
                   });
               });

AMP2: Use Network API for HTTP request/response manipulation.

const player = new bitmovin.player.Player(container, {

  advertising: {
    adClient: 'ima',
    ima: {
      onAdsManagerAvailable: ({ adsManager, adDisplayContainer }) => {
        // Example: require manual start of ad breaks
        const settings = new google.ima.AdsRenderingSettings();
        settings.autoPlayAdBreaks = false;
        adsManager.updateAdsRenderingSettings(settings);

        // Listen for a pod *before* it plays:
        adsManager.addEventListener(
          google.ima.AdEvent.Type.AD_BREAK_READY,
          (evt) => {
            // intercept here: decide to start, delay, or cancel
            // e.g., start it yourself:
            adsManager.start(); // or adsManager.discardAdBreak(); to ignore it
          }
        );
      }
    }
  }
});

Data binding

AMP1: Advanced parameterization.

{
  plugins: {
    googleanalytics: {
      trackingId: "#{accountId}",
      dimensions: {
        dimension1: "${media.title}"
      }
    }
  }
}

AMP2: Requires programmatic implementation. See the Property mapping table to fetch the required metadata.

// Bitmovin alternative - access via API
const current = player.getSource();
const videoId = current?.metadata?.videoId
const title = player.getSource().title;
const version = player.version;
// Manually construct analytics parameters

Plugins

AMP2 offers a variety of third-party extensions that work with the AMP ecosystem, including analytics, advertisement, and monetization. See Bitmovin Player Integrations for available third-party web player integrations.

Custom plugins

AMP1: Supports customized plugins that have access to player’s API and events for specific customer needs. These plugins are mostly developed by customers.

akamai.amp.AMP.registerPlugin("myplugin", MyPlugin);

AMP2: Custom plugins are not directly supported as they require integration at application level. Use player API events and methods for custom functionality.

360/180 VR playback

AMP uses A-Frame, a WebVR framework, as its primary player plugin for VR support.

AMP1 implementation:

config = {
       plugins: {
         aframe: {
           resources: [
             { src: "//aframe.io/releases/1.7.1/aframe.min.js", type: "text/javascript" },
             { src: "${paths.plugins}aframe/Aframe.min.js", type: "text/javascript"},
             { src: "${paths.plugins}aframe/Aframe.min.css", type: "text/css" }            
],
           rotation: "0 0 0",
           vrmode: true,
           native: true,
		 halfViewMode: false, //true for 180 degree playback
           components: {
             'vr-controls': {
               autoHide: 5,
               theme: {
                 foreground: "#FFF",
                 background: "#675f60",
                 window: "#675f60",
                 windowOpacity: 1,
                 backgroundOpacity: 0.5,
                 foregroundOpacity: 0.8
               }
             },
             'vr-dome': {
               src: 'https://cdn.aframe.io/360-image-gallery-boilerplate/img/city.jpg',
               crossorigin: 'anonymous'
             }
           }
       }
       },
       autoplay: false,
       playsinline: true,
       media: videos[1]
     };

AMP2 implementation:

Confirm options for 180 degree playback with a Bitmovin representative.

var conf = {
    key: 'YOUR KEY HERE',
    source: {
        title: "Bitmovin Player " + bitmovin.player.version,
        description: "VR/360° Example, contentType: single, startPosition: 0, initialRotation: true, initialRotateRate: 0.07",
        dash: '//bitmovin-a.akamaihd.net/content/vr-player/playhouse-vr/mpds/105560.mpd',
        hls: '//bitmovin-a.akamaihd.net/content/vr-player/playhouse-vr/m3u8s/105560.m3u8',
        progressive: '//bitmovin-a.akamaihd.net/content/vr-player/playhouse-vr/progressive.mp4',
        poster: '//bitmovin-a.akamaihd.net/content/vr-player/playhouse-vr/poster.jpg',
        vr: {
            startPosition: 0,
            contentType: 'single',
            initialRotation: 'true',
            initialRotateRate: 0.07
        }
    }
};

5. Migrate analytics

Review the table below for analytics provider migration details.

Analytics provider migration table

ProviderAMP1 implementationAMP2 implementationMigration steps
Chartbeat{ plugins: { chartbeat: {} } }Not integratedCustom implementation required
CMCD{ plugins: { cmcd: {} } }Integration module availableUse bitmovin-player-web-integration-cmcd
Comscore{ plugins: { comscorestreamsense: {} } }Integration moduleUse bitmovin-player-web-analytics-comscore
Conviva{ plugins: { conviva: {} } }Integration moduleUse bitmovin-player-web-analytics-conviva
Datazoom{ plugins: { datazoom: {} } }Third-party integrationFollow Datazoom documentation
Google Analytics{ plugins: { googleanalytics: {} } }App-level integrationIntegrate above player
MOAT{ plugins: { moat: {} } }Integration moduleUse bitmovin-player-web-analytics-moat
Mux{ plugins: { mux: {} } }Third-party integrationFollow Mux guide
Nielsen DCR/DTVR{ plugins: { nielsen: {} } }On roadmapWill be required by top tier customers
Adobe Analytics{ plugins: { omniture: {} } }Not directly integratedTypically through Adobe Analytics
Adobe Heartbeat{ plugins: { heartbeat: {} } }Integration moduleUse bitmovin-player-web-analytics-adobe
Segment{ plugins: { segment: {} } }Not integratedExplore per-customer basis

6. Migrate ad integration

Review how AMP1 and AMP2 implement different ad integrations.

Google IMA (VAST/VMAP)

AMP1 implementation:

{ 
  plugins: { 
    ima: {
      adTagUrl: "https://example.com/vast.xml"
    } 
  } 
}

AMP2 implementation:

advertising: {
  adBreaks: [{
    tag: {
      url: "https://example.com/vast.xml",
      type: 'vast'
    }
  }]
}

Freewheel

AMP1: Uses a full SDK integration via plugin.
AMP2: Can play Freewheel DAI streams, but this is not integrated with SDK. Use Bitmovin ads module for non-IMA ads .

Server-Side Ad Insertion (SSAI)

ProviderAMP1 supportAMP2 supportMigration notes
IMA DAIPlugin SupportedDirect migration path
YospacePlugin IntegrationUse bitmovin-player-web-integrations-yospace
AWS MediaTailorVia manifest SupportedWorks with HLS/DASH

Google IMA DAI (SSAI)

AMP1 implementation:

var config = {
  media: {
    src: "http://storage.googleapis.com/testtopbox-public/video_content/bbb/master.m3u8",
    type: "application/x-mpegURL"
    temporalType: "live",
    assetKey: "sN_IYUG8STe1ZzhIIE_ksA"
  },
  plugins: {
    imadai: {
      resources: [
        {src: "//imasdk.googleapis.com/js/sdkloader/ima3_dai.js", type: "text/javascript", async: true},
        {src: "${paths.plugins}imadai/Imadai.js", type: "text/javascript", async: true}
      ]
    }
  },
};
akamai.amp.AMP.create("amp", config);

AMP2 implementation:

As of the time this migration guide was written, no prominent DAI integration example had been identified, while DAI is listed as an available integration. Check with a Bitmovin representative for SSAI guidance with Google’s IMA DAI SDK.

Yospace (SSAI)

AMP1 implementation:

var config = {
  plugins: {
    yospace: {
        debug: true,
        resources: [
          {src: "yo-ad-management.min.js", type: "text/javascript"},
          {src: "../akamai/amp/amp-yospace/Yospace.js", type: "text/javascript"}
        ]
      }
    }
  }
};

akamai.amp.AMP.create("amp", config);

AMP2 implementation:

const yospaceConfig: YospaceConfiguration = {
debug: true,
};

const bitmovinYospacePlayer = new BitmovinYospacePlayer(Player, playerContainer, conf, yospaceConfig);

7. Migrate DRM configuration

AMP1 implementation:

var config = {
    media: {
        source: [{
            src: "https://example.com/stream.mpd",
            type: "application/dash+xml",
        }, {
            src: "https://example.com/stream.m3u8",
            type: "application/x-mpegURL",
        }],
        keys: {
            "com.widevine.alpha": {
                "serverURL": "https://license-server.com/widevine"
            },
            "com.microsoft.playready": {
                "serverURL": "https://license-server.com/playready",
                "httpRequestHeaders": {
                    "http-header-CustomData": "eyJ1c2VySWQiOiIxM..."
                }
            },
            "com.apple.fps.1_0": {
                "serverURL": "https://license-server.com/fairplay",
                "cert": "https://example.com/certificate.cer"
            }
        }
    }
}

AMP2 implementation:

{
  source: {
    dash: "https://example.com/stream.mpd",
    drm: {
      widevine: {
        LA_URL: "https://license-server.com/widevine",
        headers: {
          "X-Custom-Header": "value"
        }
      },
      playready: {
        LA_URL: "https://license-server.com/playready"
      },
      fairplay: {
        LA_URL: "https://license-server.com/fairplay",
        certificateURL: "https://example.com/certificate.der"
      }
    }
  }
}

8. Migrate UI customization

You can migrate UI customization through theme configuration API and pseudo CSS style rules.

AMP1 implementation:

  • React UI Theme setting
{
  plugins: {
    react: {
      theme: {
          text: "#746A3C",
          foreground: "#C2B49B",
          background: "#2E3D33"
        },
    }
  }
}
  • React UI CSS style
<style>
  .amp-icon:hover {
    color: #B98853;
  }
  .amp-playpause {
    color: #B18742
  }
</style>

AMP2 implementation:

  • UI framework
// Bitmovin UI - open source framework
const uiConfig = {
  variant: 'custom',
  customCss: 'path/to/custom.css'
};
const player = new Player(container, {
  ui: uiConfig
});
<style>
#player .bmpui-ui-controlbar {
  background: rgba(10,10,12,0.8);
  height: 48px;
}

#player .bmpui-ui-playbacktogglebutton {
  border-radius: 9999px;
  width: 40px; height: 40px;
}

</style>