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:
- Documentation: AMP2 Bitmovin Player docs, AMP1 TechDocs
- Demos and code samples: AMP2 Bitmovin Code Samples, AMP1 Demos
- Event Mapping Tool
- API Mapping Tool
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 transform | AMP2 event | Migration notes | Code example |
---|---|---|---|
adbreak | onAdsManagerAvailable | Coult integrate accessing IMA’s ad manager | See Ad break transforms |
adrequest | N/A | Could integrate with preprocessHttpRequest | See Ad request transforms |
cuechange | cueenter , cueupdate | Direct mapping | player.on(‘cueenter’, callback) |
error | error | Direct mapping | player.on(‘error’, callback) |
media | media | Could integrate with preprocessHttpRequest | See 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
Provider | AMP1 implementation | AMP2 implementation | Migration steps |
---|---|---|---|
Chartbeat | { plugins: { chartbeat: {} } } | Not integrated | Custom implementation required |
CMCD | { plugins: { cmcd: {} } } | Integration module available | Use bitmovin-player-web-integration-cmcd |
Comscore | { plugins: { comscorestreamsense: {} } } | Integration module | Use bitmovin-player-web-analytics-comscore |
Conviva | { plugins: { conviva: {} } } | Integration module | Use bitmovin-player-web-analytics-conviva |
Datazoom | { plugins: { datazoom: {} } } | Third-party integration | Follow Datazoom documentation |
Google Analytics | { plugins: { googleanalytics: {} } } | App-level integration | Integrate above player |
MOAT | { plugins: { moat: {} } } | Integration module | Use bitmovin-player-web-analytics-moat |
Mux | { plugins: { mux: {} } } | Third-party integration | Follow Mux guide |
Nielsen DCR/DTVR | { plugins: { nielsen: {} } } | On roadmap | Will be required by top tier customers |
Adobe Analytics | { plugins: { omniture: {} } } | Not directly integrated | Typically through Adobe Analytics |
Adobe Heartbeat | { plugins: { heartbeat: {} } } | Integration module | Use bitmovin-player-web-analytics-adobe |
Segment | { plugins: { segment: {} } } | Not integrated | Explore 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)
Provider | AMP1 support | AMP2 support | Migration notes |
---|---|---|---|
IMA DAI | Plugin | ✓ Supported | Direct migration path |
Yospace | Plugin | ✓ Integration | Use bitmovin-player-web-integrations-yospace |
AWS MediaTailor | Via manifest | ✗ Supported | Works 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>
- UI resources:
- UI Factory for pre-configured interfaces.
- Open-source UI framework .
- Full customization possible.
- See Bitmovin Player UI for more information.
Updated about 3 hours ago