GithubHelp home page GithubHelp logo

bitmovin / bitmovin-player-ui Goto Github PK

View Code? Open in Web Editor NEW
127.0 26.0 77.0 19.65 MB

The Bitmovin Adaptive Streaming Player UI

License: MIT License

JavaScript 1.16% HTML 3.90% TypeScript 87.46% SCSS 6.96% Shell 0.53%
bitmovin player ui

bitmovin-player-ui's Introduction

Bitmovin Player UI npm version Build Status

The Bitmovin Adaptive Streaming Player UI

Read more about the usage, along with other important information about the Bitmovin Player at https://bitmovin.com/ and https://bitmovin.com/docs/player.

Installation

The UI framework is also available through the following distribution channels:

CDN

The UI framework and default skin bundled with the latest player release are always available via CDN. This is the recommended way if you just want to work with the predefined UI components. All components will be available in the bitmovin.playerui namespace.

  • JavaScript library: //cdn.bitmovin.com/player/web/8/bitmovinplayer-ui.js
  • CSS default skin: //cdn.bitmovin.com/player/web/8/bitmovinplayer-ui.css

NPM

The UI framework is also available in the NPM repository and comes with all source and distributable files, JavaScript modules and TypeScript type definitions.

  • npm install bitmovin-player-ui

Getting Started with Development

  1. Clone Git repository
  2. Install node.js
  3. Install Gulp: npm install --global gulp-cli
  4. Install required npm packages: npm install
  5. Run Gulp tasks (gulp --tasks)
  • gulp to build project into dist directory
  • gulp watch to develop and rebuild changed files automatically
  • gulp serve to open test page in browser, build and reload changed files automatically
  • gulp lint to lint TypeScript and SASS files
  • gulp build-prod to build project with minified files into dist directory

To take a look at the project, run gulp serve. For changes, check our CHANGELOG. This UI framework version is for player v8. The UI framework for player v7 can be found in the support/v2.x branch.

Contributing

Pull requests are welcome! Please check the contribution guidelines.

Introduction

This repository contains the Bitmovin Player UI framework introduced with the 7.0 release. It is designed as a flexible and modularized layer on the player API that replaces the old integrated monolithic UI, enabling customers and users of the player to easily customize the UI to their needs in design, structure, and functionality. It makes it extremely easy and straightforward to add additional control components and we encourage our users to proactively contribute to our codebase.

The framework basically consists of a UIManager that handles initialization and destruction of the UI, and components extending the Component base class. Components provide specific functionality (e.g. PlaybackToggleButton, ControlBar, SeekBar, SubtitleOverlay) and usually consist of two files, a TypeScript .ts file containing control code and API interaction with the player, and a SASS .scss file containing the visual style.

A UI is defined by a tree of components, making up the UI structure, and their visuals styles, making up the UI skin. The root of the structure always starts with a UIContainer (or a subclass, e.g. CastUIContainer), which is a subclass of Container and can contain other components, like any other components extending this class (usually layout components, e.g. ControlBar). Components that do not extend the Container cannot contain other components and therefore make up the leaves of the UI tree.

Customizing the UI

There are three approaches to customize the UI:

  1. Go with the built-in UI of the player and adjust the styling to your liking with CSS
  2. Keep the player managing the UI internally but tell it to load alternative UI CSS/JS files, e.g. your own build from this repository
  3. Deactivate the built-in UI and manage your own UI instance externally, e.g. your own build from this repository

Styling the built-in UI

When using the built-in UI, you can style it to your linking with CSS by overwriting our default styles, as documented in our CSS Class Reference.

Replacing the built-in UI

Internally managed by the player

It is possible to override which js and css files the player loads for its internal UI with the ui and ui_css properties in the location section of the player configuration. This is a simple way to supply a customized UI without the overhead of managing an external UI instance, and especially helpful for supplying a custom script which otherwise cannot be overridden like the CSS styles can. The paths to the ui (js) and ui_css (obviously css) files can be absolute or relative. Both are optional and do not need to be specified together.

The player constructs its internal UI instance from the UIFactory.buildDefaultUI(player) factory method, so this entry point must exist for this approach to work.

import { Player } from 'bitmovin-player';

const config = {
  ...,
  location: {
    ui: '//domain.tld/path/to/bitmovinplayer-ui.js',
    ui_css: 'styles/bitmovinplayer-ui.css',
  },
};

const player = new Player(document.getElementById('container-id'), config);

Externally managed

To use the player with an external custom UI instance, you need to deactivate the built-in UI (set ui: false), include the necessary js and css files into your HTML and create and attach your own UI instance with the UIManager.

  • Deactivate the built-in UI by setting ui: false in the config of the player (Player Configuration Guide)
  • Build the UI framework (e.g. gulp build-prod) and include bitmovinplayer-ui.min.js and bitmovinplayer-ui.min.css (or their non-minified counterparts) from the dist directory
  • Create your own UI instance with the UIFactory once the player is loaded (or load a custom UI structure)
import { Player } from 'bitmovin-player';
import { UIFactory } from 'bitmovin-player-ui';

const config = {
  ...,
  ui: false, // disable the built-in UI
};

const player = new Player(document.getElementById('container-id'), config);
const myUiManager = UIFactory.buildDefaultUI(player);

Building a custom UI structure

Instead of using predefined UI structures from the UIFactory, you can easily create a custom structure. For examples on how to create such UI structures, take a look at the UIFactory or DemoFactory.

A simple example on how to create a custom UI with our default skin that only contains a playback toggle overlay (an overlay with a large playback toggle button) looks as follows:

import { Player } from 'bitmovin-player';
import { PlaybackToggleOverlay, UIContainer, UIManager } from 'bitmovin-player-ui';

// Definition of the UI structure
const mySimpleUi = new UIContainer({
  components: [
    new PlaybackToggleOverlay(),
  ],
});

const player = new Player(document.getElementById('container-id'), config);
const myUiManager = new UIManager(player, mySimpleUi);

UIManager

The UIManager manages UI instances and is used to add and remove UIs to/from the player. To add a UI to the player, construct a new instance and pass the player object, a UI structure (UIContainer) or a list of UI structures with conditions (UIVariant[]), and an optional configuration object. To remove a UI from the player, just call release() on your UIManager instance.

import { UIManager } from 'bitmovin-player-ui';

// Add UI (e.g. at player initialization)
const myUiManager = new UIManager(player, mySimpleUI);

// Remove UI (e.g. at player destruction)
myUiManager.release();

UIs can be added and removed anytime during the player's lifecycle, which means UIs can be dynamically adjusted to the player, e.g. by listening to events. It is also possible to manage multiple UIs in parallel.

Here is an example on how to display a special UI in fullscreen mode:

import { Player, PlayerEvent, ViewMode } from 'bitmovin-player';
import { UIManager } from 'bitmovin-player-ui';

const player = new Player(document.getElementById('container-id'), config);
let myUiManager = new UIManager(player, myWindowUi);
  
player.on(PlayerEvent.ViewModeChanged, (event) => {
  myUiManager.release();
  if (event.from === ViewMode.Fullscreen) {
    myUiManager = new UIManager(player, myFullscreenUi);
  } else {
    myUiManager = new UIManager(player, myWindowUi);
  }
});

Alternatively, you can let the UIManager handle switching between different UIs by passing in multiple UIVariants:

import { Player } from 'bitmovin-player';
import { UIManager } from 'bitmovin-player-ui';

const player = new Player(document.getElementById('container-id'), config);
const myUiManager = new UIManager(player, [{
  // Display my fullscreen UI under the condition that the player is in fullscreen mode
  ui: myFullscreenUi,
  condition: (context) => context.isFullscreen,
}, {
  // Display my window UI in all other cases
  ui: myWindowUi,
}]);

There are various conditions upon which the UIManager can automatically switch between different UIs, e.g. ad playback and player size.

Factory

UIFactory provides a few predefined UI structures and styles, e.g.:

  • buildDefaultUI: The default UI as used by the player by default
  • buildDefaultCastReceiverUI: A light UI specifically for Google Cast receivers
  • buildDefaultSmallScreenUI: A light UI specifically for small handheld devices
  • buildDefaultTvUI: A UI specifically for big screens with remote control ans main input option

You can easily test and switch between these UIs in the UI playground.

Components

For the list of available components check the src/ts/components directory. Each component extends the Component base class and adds its own configuration interface and functionality. Components that can container other components as child elements extend the Container component. Components are associated to their CSS styles by the cssClass config property (prefixed by the cssPrefix config property and the $prefix SCSS variable).

Custom components can be easily written by extending any existing component, depending on the required functionality.

Component Configuration

All components can be directly configured with an optional configuration object that is the first and only parameter of the constructor and defined by an interface. Each component is either accompanied by its own configuration interface (defined in the same .ts file and named with the suffix Config, e.g. LabelConfig for a Label), or inherits the configuration interface from its superclass.

There is currently no way to change these configuration values on an existing UI instance, thus they must be passed directly when creating a custom UI structure.

The following example creates a very basic UI structure with only two text labels:

import { Label, UIContainer } from 'bitmovin-player-ui';

const myUi = new UIContainer({
  components: [
    new Label({ text: "A label" }),
    new Label({ text: "A hidden label", hidden: true })
  ],
});

The UIContainer is configures with two options, the components, an array containing child components, and cssClasses, an array with CSS classes to be set on the container. The labels are configures with some text, and one label is initially hidden by setting the hidden option.

UI Configuration

The UIManager takes an optional global configuration object that can be used to configure certain content on the UI.

import { UIManager } from 'bitmovin-player-ui';

const myUiConfig = {
  metadata: {
    title: 'Video title',
    description: 'Video description...',
  },
  recommendations: [
    {title: 'Recommendation 1: The best video ever', url: 'http://bitmovin.com', thumbnail: 'http://placehold.it/300x300', duration: 10.4},
    {title: 'Recommendation 2: The second best video', url: 'http://bitmovin.com', thumbnail: 'http://placehold.it/300x300', duration: 64},
    {title: 'Recommendation 3: The third best video of all time', url: 'http://bitmovin.com', thumbnail: 'http://placehold.it/300x300', duration: 195},
  ],
};

const myUiManager = new UIManager(player, myUi, myUiConfig);

All the configuration properties are optional. If metadata is set, it overwrites the metadata of the player configuration. If recommendations is set, a list of recommendations is shown in the RecommendationOverlay at the end of playback. For this to work, the UI must contain a RecommendationOverlay, like the default player UI does.

UI Localization

The UI can be localized by calling UIManager.setLocalizationConfig() function before initializing a UIManager. It ships with English and German translations und uses English by default. Additional translations can be added via the LocalizationConfig, where the automatic language detection can also be disabled.

Please note that the LocalizationConfig is a singleton for all UI instances, i.e. it is currently not possible to configure the UI language per UIManager instance. This is also the reason why UIManager.setLocalizationConfig() must be called before creating a UIManager instance for the configuration to be applied as expected.

const myLocalizationConfig = {
  // Automatically select a language fitting the browser language
  // (falls back to English if no language that matches the browser language is defined)
  language: 'auto',
  vocabularies: {
    de: {
      'settings': 'Einstellungen',
      ...
    },
    fr: {
      ...
    },
  },
};

// First we set the localization configuration
UIManager.setLocalizationConfig(myLocalizationConfig);
// Then we create a UI instance
const myUiManager = new UIManager(...);

The UIManager also has a localize function which can be used to translate custom labels in user-created component instances. The vocabulary can be extended by adding custom keys to LocalizationConfig.vocabularies. If a key is not present in the vocabulary, localize will simply fallback to the key.

const myLocalizationConfig = {
  ...,
  vocabularies: {
    en: {
      'my.custom.key': 'my custom key',
      'this will also act as a key': 'my custom key 2',
    },
    de: {
      'my.custom.key': 'my german translation',
    },
  },
};

const label1 = new Label({ text: UIManager.localize('my.custom.key') });

// This key only exists in the English vocabulary, so it will be translated in English and
// fallback to the key string in any other language
const label2 = new Label({ text: UIManager.localize('this will also act as a key') });

// This key does not exist in any vocabulary and will never be localized - it is basically the
// same as setting the text directly (e.g. `{ text: 'This is not included in vocabulary' }`)
const label3 = new Label({ text: UIManager.localize('This is not included in vocabulary') }); 

The default vocabularies along with the keys can be found in the languages folder.

UI Playground

The UI playground can be launched with gulp serve and opens a page in a local browser window. On this page, you can switch between different sources and UI styles, trigger API actions and observe events.

This page uses BrowserSync to sync the state across multiple tabs and browsers and recompiles and reloads automatically files automatically when any .scss or .ts files are modified. It makes a helpful tool for developing and testing the UI.

bitmovin-player-ui's People

Contributors

andr3wid avatar bitmovin-kenny avatar dependabot[bot] avatar dweinber avatar fabiandev avatar felix-hoc avatar flofischer avatar halfbyteheroes avatar hanneslinder avatar huysbs avatar jdgo-mars avatar jmsn avatar kishorens avatar luckygoyal-bitmovin avatar ludomichaud avatar mcarriga avatar mimcz avatar mukulmishra18 avatar nikolanikushev avatar oberhamsi avatar offnertho avatar protyposis avatar reevn avatar since avatar stonko1994 avatar succo avatar teslaadis avatar thomhs22 avatar vzablock avatar wasp898 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitmovin-player-ui's Issues

Handling custom state in player UI

Iโ€™m trying to implement functionality to create clips within a video. Each clip has a start and end time. Extending the UI within the player is mostly done, and follows the same patterns as the rest of the UI (many small components that are composed in UIManager.Factory). However, I need to share state between these components, and besides using local storage itโ€™s unclear to me what my options are. I see that many existing components gets state from the player itself, but itโ€™s probably not meant to be extended?

Could you point me in the right direction? Please let me know if this is more of a support issue, and Iโ€™ll use that channel instead.

Autoplay handling

The UI should render the play button in state playing (display pause icon in play button, hide play overlay in huge playback button) when an autoplay video is starting.

The player works as follows:

  • "Normal" play: new Player() -> player.setup({ source }) -> player.play() -> ON_PLAY -> ON_PLAYING or ON_PAUSED+ON_WARNING 5008 (when playback is blocked, e.g. play() call without user interaction)
  • Autoplay: new Player() -> player.setup({ source, playback: { autoplay: true }}) -> ON_PLAYING or ON_WARNING 5008 (if autoplay is blocked, e.g. due to audio)

In case of autoplay, there is no ON_PLAY event because playback is triggered implicitly, i.e. without an API play() call, and also no ON_PAUSED call if it fails because ON_PAUSED can only come after an ON_PLAY. So if autoplay works, we get an ON_PLAYING event, and if it fails, we get an ON_WARNING event with code 5008.

When the UI is initialized after the player setup has finished, there is no way to check if the autoplay attempt has already happened and failed, or if it is upcoming, so we cannot rely on the autoplay config flag when the player is ready. In this case, we simply rely on the playing state.

Seek doesn't work when player is in playback-finished status

  1. Load a video and let it play until the end
  2. Seek to some point in the video

Expected : Video should go to the seek position and stay there
Actual: Player seems to start seeking, but never ends

Just realized, that this probably should go to the player repo, but i cannot delete it

Multiple taps required to start live stream (iOS, Android)

Using Player Version 7.2.2 and UI Version 2.7.1, I'm seeing the same behaviour as reported in issue #10 - on iOS (10.3.2, 10.3.3beta, 9.3.2) I have to tap at least twice, sometimes three times to initiate playback of a live stream.

Android / Chrome 59.0.3071.125 seems to have a similar issue.

It's as if one tap on the big play button brings up the UI, another tap sends the UI away, and the third starts playback.

Test stream is here, using latest player and default UI: http://swisscomstream.ch/player/bitmovin7latest_AD.php

Where we report are general bitmovin player bugs? player.getAvailableSegments() api func. very very long response time depend on playlist length

var s1 = performance.now()
var a = bitmovin.player('playerLiveTvBitmovin')
a.getAvailableSegments()
var s2 = performance.now()
console.log("s2-s1 -> " , s2-s1)

Result :>> s2-s1 -> 20509.90000006277

This is very long sync operation and exponential incerease to manifest length. It will be basic and fast. Why it is very slow calculate for available segments??

Typescript definitions are not compatible with `strictNullChecks` mode

The error:

Property 'value' of type 'string | undefined' is not assignable to string index type 'string'..

is located in bitmovin-player-ui/src/ts/player.d.ts (678,7):

interface MediaTrackRole {
    schemeIdUri: string;
    value?: string;
    id?: string;
    [key: string]: string;
}

This is because in strictNullChecks mode type of value and id evaluate to string | undefined which is incompatible with [key: string]: string index signature.
It should be changed to [key: string]: string | undefined; if id and value might be undefined.

Playing on the mobile devices requires double tap

Hi Guys,

As in the title, currently playing the video on the mobile device requires user to tap the player overlay twice (first to bring up UI, then start video playing). Is there any way to start video playback within single tap?

Best,
I.

LGPL v3.0 - Why?

We do commercial software so LGPL v3.0 is banned in our company. We are only allowed to use MIT, Apache2.0, and BSD, or carefully considered commercial licenses (we're not against paying as long as we retain rights in what WE code, even when we use someone's API to do it).

I understand that Bitmovin player is a for-fee player, but your use of LGPL v3 is a hairball nightmare for anyone who wants to sell their work. LGPL has very tricky legal requirements with "code conveyance language" (i.e. being forced to give away your code if you use the Linked Library), other tricky "dynamic" linking legalese, and public documentation requirements. It's simply a toxic license for most people in the commercial software world.

-- Question: is there a link to a commercial license. BTW, a sloppy commercial license is no better and should carefully consider the property rights of BOTH parties, anything else is just another kind no-go hairball.

-- Observation: you only have 35 stars after 1 year on Github. It may be related to licensing because it looks like you're doing some nice engineering work!

Thanks.

Allow UI creation before player.load

Currently it is not possible to create a UI instance before a source has been loaded, which is a problem because then the UI never displays errors from a failed player.load(source).

We need to allow the creation of a UIManager after the new Player(container, config) constructor, which means

  • components must not at all or only gracefully access the player API before Event.SourceLoaded and avoid errors
  • initialize themselves on Event.SourceLoaded
  • this might be a good moment to implement

    Don't fire a fake SourceLoaded event from the UIManager when the UI is initialized, rather add a UI onReady event that is triggered when the UI is initialized and when SourceLoaded events from the player are received (the goal should be to get rid of uiSourced events (and playerWrapper.fireEventInUI) and the necessity to differentiate them from "real" player events)
    from #111

Enable playback speed selector by default

In #125 we introduced a flag to hide the PlaybackSpeedSelectionBox, we also accidentally disabled the Selection by default.

The default should be to show the PlaybackSpeed Selection Box.

Watermark too small in IE11

Since #180 is merged, the watermark in IE11 is too small:

image

Seems like background-size: initial does not work as intended there.

Support paging in SettingsPanel

Current state

Different setting groups need to be added into different SettingsPanel instances, and these panels need to be switched on/off to switch between the setting groups.

Example: SettingsToggleButton opens a SettingsPanel with a SubtitleSettingsOpenButton that opens another SettingsPanel instance, the SubtitleSettingsPanel. The SubtitleSettingsOpenButton hides the SettingsPanel and shows the SubtitleSettingsPanel, and the SubtitleSettingsCloseButton does the inverse. This results in a odd UX and has the side effect that the SettingsToggleButton is only in the active state while its "own" SettingsPanel` is shown, but it does not know anything about "sub-settings panels".

Desired state

A SettingsPanel should be a container for multiple pages/panes, which can be navigated. In our example, we could have a MainSettingsPage and a SubtitleSettingsPage within the SettingsPanel and switch between them with navigation actions (e.g. via API or buttons). There could even be nice animated transitions. The UX would be nicer and the problem with the wrongly inactive SettingsToggleButton solved too.

Remove legacy skin

Remove the legacy skin which isn't really used by anybody and remove the skin name marker class (ui-skin-modern). The marker classes were introduced to allow loading the CSS of multiple skin and switch between them easily - in case this is still required, the CSS files can still be dynamically unloaded / loaded.

Implement ListBox

Add an implementation of the ListSelector as a DOM element-based ListBox. In contrast to the SelectBox, it does not render a dropdown panel but displays the items in a stacked list one above the other. The items could be implemented by reusing the Button component.

The ListBox should fill a SettingsPanel with its items, and the use-case is for example a SettingsPanel that opens and directly offers a selection of all subtitles or audio tracks, without the user having to navigate into another "deeper level" like he has to with the dropdown panel of a SelectBox (a SettingsPanel with a single SelectBox is bad UX and unnecessarily complicated). It will thus make sense to implement subclasses like SubtitleListBox and AudioTrackListBox etc., analogous to SubtitleSelectBox, AudioTrackSelectBox etc. Ideally, common code would be shared across both implementations because they both build upon the same ListSelector interface.

The SettingsPanelItem with its label needs to be revised for this, as it makes more sense to have the label on top instead of on the left, wasting a lot of precious space. Or it might be completely left away because the purpose of the panel might be obvious from the button that opens it or the content it displays.

Don't animate HugePlaybackToggleButton on initialization

When the HugePlaybackToggleButton is initialized and rendered for the first time, the button fades in with an animation if the player is paused, or fades out with an animation if the player is player.

The button should simple be displayed or not displayed without any animation when it is initially rendered.

Add skip x seconds forward/backward button

As it's becoming a trend to provide buttons that skip 10 or 30 seconds forward / backward, we should add these to the framework.

  • SkipButton with configuration properties direction: enum SkipButtonDirection { Forward, Backward } (or would it be better to have separate SkipForwardButton and SkipBackwardButton?) and duration: number (time in seconds to skip)
  • Skipping is simply implemented as a seek from the current time
  • Icons need to be designed
  • Button(s) should be usable in the control bar as well as in the HugePlaybackButton overlay

Use of Prettier/large diffs when maintaining custom UI

Iโ€™m currently setting up a custom UI, and I need to maintain my own version of bitmovin-player-ui. I like to use Prettier with format-on-save enabled, both because it takes the hassle out of formatting code, but also because it is easy to detect wether or not the code compiles.

Are you using/have you considered using Prettier internally โ€“ and in any case would you share your settings? That would make the diffs a lot smaller.

Switch play buttons to paused state when playback is rejected by browser

Some browsers, e.g. Safari and Chrome, reject playback without user interactions under certain circumstances (e.g. unmuted audio playback). The player fires an ON_WARING event with code 5008 in such a case, but the UI does not react to it.

In the case where the UI is initialized between a play() call on the player (or an autoplay attempt) and the play rejection, the playback buttons switch into the playing state but do not switch back when the play attempt fails with the warning.

TvNoiseCanvas.renderFrame called after player.destroy

After player.destroy() also the UI should be destroyed correctly.

Steps to reproduce:

  1. Load the player with the UI and force an error (e.g. set an unreachable URL as source).
  2. Call player.destroy()
  3. Pause the JS execution and it will probably land somewhere in TvNoiseCanvas.renderFrame

Setting startTime stops any playback

Setting startTime in options when setting up the player causes playback to halt. The video loads, and all other player features appear to work, but actual playback can never be initiated.

Steps to reproduce:

  1. Load the player, e.g. var player = bitmovin.player('player-wrapper');
  2. call player.setup(config), with config containing some arbitrary start time in seconds, e.g. { options: { startTime: 123 }
  3. Attempt to play the video. Note that the player fetches the content, and all player functionality appropriately fires the correct events, but playback never actually starts.

Persist Users Video Quality Selection

bitmovin.player.version: ^7.8.2
bitmovin.playerui.version: 2.18.0

I've tried saving the user video quality bit rate a couple of different ways and nothing seems to work.

  1. store their selection in localStorage and try to load that startupBitrate bit rate.
  2. store the id of the bitrate in localStorage and set the bit rate based on that id
    • I found that the id for the same bitrate across multiple videos is different so this is kind of useless.

Is this a bug or am I missing something completely? I've scoured the docs for more time than I'd like to admit.

Add API to dynamically manage timeline markers

Currently it is possible to add generic TimelineMarker markers to the timeline (i.e. SeekBar), but only via the UIConfig at construction time of the UIManager.

The time line marker interface:

export interface TimelineMarker {
time: number;
title?: string;
}

The UI config interface that takes an array of timeline markers:

export interface UIConfig {
/**
* Specifies the container in the DOM into which the UI will be added. Can be a CSS selector string or a
* HTMLElement object. By default, the player figure will be used ({@link PlayerAPI#getFigure}).
*/
container?: string | HTMLElement;
metadata?: {
title?: string;
description?: string;
markers?: TimelineMarker[];
};
recommendations?: UIRecommendationConfig[];
}

The constructor that takes the config:

constructor(player: PlayerAPI, uiVariants: UIVariant[], config?: UIConfig);

We need an API that allows dynamic management of these markers, i.e. add and remove during the lifetime of the UIManager. Additionally we want to be able to define different kinds of markers, e.g. chapter and ad markers that need to look and possibly work differently.

Currently these markers mark points in time. We also want to be able to mark time intervals. While this should be easily achievable to mark intervals of the main content, it is going to be more difficult for inserted ad breaks that modify the timeline, so we may want to handle this in a separate follow-up issue once necessary. The API for this would be quite simple, but the question of how this is rendered on a seek bar is to be discussed (e.g. how do we transform the timeline of the seekbar if an ad interval is inserted? how is the mapping from the seekbar to the content done? how do we even know in advance how long an ad break is going to be?).

Safari on Mac emits onPlayerResize event constantly

Hi Guys,

Safari on Mac is constantly emitting onPlayerResize event blocking the player from loading. It's happening on the latest branch release/v2.0.0-rc1 build with all default settings (player JS loaded from beta channel). It's behaving that way on the latest and few last versions of Safari.
According to the release notes I think it was fixed once in v6.1.8

bitmovin-onresize-bug

[TS] Incorrect DRMConfig type

Right now we have empty DRMConfig interface:

interface DRMConfig {
}

which is extended by other types, like:

interface WidevineModularDRMConfig extends DRMConfig {
  //...
}

I would propose renaming it to BaseDRMConfig if there are some common fields.
Then the DRMConfig would be:

interface DRMConfig = {
  playready: PlayReadyDRMConfig;
  widevine: WidevineModularDRMConfig;
  // ...
}

Which is correct type of SourceConfig drm property, according to docs:
https://bitmovin-a.akamaihd.net/bitmovin-player/stable/7/docs/interfaces/playerconfigapi.sourceconfig.html

index.html is broken, "TypeError: player.isAirplayAvailable is not a function", v7.0.5

Hi there,

I've been trying to run index.html UI demo, but unfortunately I'm getting error "TypeError: player.isAirplayAvailable is not a function". See attached screenshot.

screenshot_10

Whenever I'm trying to switch anything using selectboxes below player, player goes black with another error "Uncaught TypeError: Cannot read property 'release' of undefined".

Chrome 55.0.2883.87 m.

Best,
Irek

2.10.4 addSubtitle in demo is broken

Hi guys, wenn i click on addSubtitle in the demo (gulp serve), i'm seeing an error in the console

bitmovinplayer.js:11 Uncaught TypeError: Cannot read property 'hasOwnProperty' of undefined at j0z.(anonymous function) [as addSubtitle] (https://bitmovin-a.akamaihd.net/bitmovin-player/stable/7.4/bitmovinplayer.js:11:697015) at J1x.(anonymous function).(anonymous function) [as addSubtitle] (https://bitmovin-a.akamaihd.net/bitmovin-player/stable/7.4/bitmovinplayer.js:11:721312) at HTMLButtonElement.<anonymous> (http://localhost:9000/:348:33) at HTMLButtonElement.dispatch (https://code.jquery.com/jquery-3.1.0.min.js:3:9922) at HTMLButtonElement.q.handle (https://code.jquery.com/jquery-3.1.0.min.js:3:7949) (anonymous function) @ bitmovinplayer.js:11 J1x.(anonymous function).(anonymous function) @ bitmovinplayer.js:11 (anonymous) @ (index):348 dispatch @ jquery-3.1.0.min.js:3 q.handle @ jquery-3.1.0.min.js:3

CC/Subtitle Option Missing in IE11

Subtitles option in the settings panel does not appear in IE11.
On all other browsers, the video quality, speed and subtitles option are visible, but on IE11, the subtitles option is missing.

image

ES6 exports

Replace the module.exports assignment with ES6 export statements.

Changing the volume while muted should also unmute the player

Starting with v8.0.0 we now separate between being in a muted state and the volume being set to 0. When the player is in the muted state and the volume is changed, the player will not accept the new volume and still stay in the muted state.

Optimally, we would also unmute the player when changing the volume.

Add localization for strings

Text strings in the UI are currently all hardcoded in English. Most strings can be changed by creating a custom UI structure and setting the labels, but not all of them.

A decent localization interface would not require users at all to create a custom UI structure. It should work with the player's default UI by supplying localized strings to the player config.

Question about player.EVENT.ON_AD_SKIPPED

Hi there,

I am trying this ui on our product with video ad,
I found out after I click skip button, the ad does being eliminated, but EVENT.ON_AD_SKIPPED isn't fired.

I have checked your implementation is simply calling player.skipAd();
https://github.com/bitmovin/bitmovin-player-ui/blob/master/src/ts/components/adskipbutton.ts#L75

since bitmovin js player isn't a open source project, I have no way to check if EVENT.ON_AD_SKIPPED is dispatched after player.skipAd() at some point.

Can you kindly check if this event really being dispatched when player.skipAd?

Btw, our product only use bitmovin player to play VAST ad,
so config.source is left empty.
just FYI, don't know if this setting would affect the dispatch of EVENT.ON_AD_SKIPPED

Thanks!

Seekbar overlaps live indicator

When playing a live stream and then call e.g. player.timeShift(10), the seekbar starts to overlap the live indicator, and then when playback resumes it continues to move out of the picture:

image

Typescript definitions doesn't work

There's some problem with building or publishing this package on npm.

Here is the content of main.d.ts file in node_modules:

/// <reference path="../../../src/ts/player.d.ts" />
export {};

It results in no typings at all:

image

I've installed latest version "bitmovin-player-ui": "^2.13.0"

PlaybackToggleButton does not work when initiated through bitmovin.playerui.UIManager

Hi,

PlaybackToggleButton (that small play button on the bottom-left side) does not seem to work when it's set in UI container via bitmovin.playerui.UIManager. Clicking on it emits events however it's not doing anything with the player playback. Neither playing (when video is paused) nor pausing does not work. HugePlaybackToggleButton seems to work fine.

Simplest UI which reproduces this error is attached.

sample-code.txt

best,
Irek

Timeline markers are not updating after switching source

When you load a source with timeline-markers (source.markers) first and afterwards loading a source without timeline-markers the old ones are still there.

Similar could happen to recommendations title & description.

Affected Versions: 2.18.x / 3.x

EDIT:
This happened because the uiConfig was not copied but merged with the config passed to the player.

Add API to switch UI variants

Currently it is possible to define different UI variants that are switched according to criteria provided by the UIConditionContext object when certain player events happen. This means it is only possible to set the criteria for certain UI variants at setup, but switching is done autonomously and internally in the UIManager without any means to interfere from outside. Desired is an API that also allows to trigger switching from outside at any desired time.

The UIConditionContext upon which the target UI variant is evaluated:

/**
* The context that will be passed to a {@link UIConditionResolver} to determine if it's conditions fulfil the context.
*/
export interface UIConditionContext {
/**
* Tells if the player is loading or playing an ad.
*/
isAd: boolean;
/**
* Tells if the ad allows a UI. This is currently only true for VAST ads and cannot be used to differentiate between
* different ad clients (i.e. to display different UIs for different ad clients).
* @deprecated Will be removed in an upcoming major release, use {@link #adClientType} instead.
*/
isAdWithUI: boolean;
/**
* Tells the ad client (e.g. 'vast, 'ima') if {@link #isAd} is true.
*/
adClientType: string;
/**
* Tells if the player is currently in fullscreen mode.
*/
isFullscreen: boolean;
/**
* Tells if the UI is running in a mobile browser.
*/
isMobile: boolean;
/**
* Tells if the player is in playing or paused state.
*/
isPlaying: boolean;
/**
* The width of the player/UI element.
*/
width: number;
/**
* The width of the document where the player/UI is embedded in.
*/
documentWidth: number;
}

Example UI variants and criteria setup:

return new UIManager(player, [{
ui: modernSmallScreenAdsUI(),
condition: (context: UIConditionContext) => {
return context.isMobile && context.documentWidth < smallScreenSwitchWidth && context.isAdWithUI;
},
}, {
ui: modernAdsUI(),
condition: (context: UIConditionContext) => {
return context.isAdWithUI;
},
}, {
ui: modernSmallScreenUI(),
condition: (context: UIConditionContext) => {
return context.isMobile && context.documentWidth < smallScreenSwitchWidth;
},
}, {
ui: modernUI(),
}], config);
}

The events that trigger the evaluation of the context and potentially switch the UI variant:

// Listen to the following events to trigger UI variant resolution
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_READY, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_PLAY, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_PAUSED, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_STARTED, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_FINISHED, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_SKIPPED, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_ERROR, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_PLAYER_RESIZE, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_FULLSCREEN_ENTER, resolveUiVariant);
this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_FULLSCREEN_EXIT, resolveUiVariant);

how to run the example?

I'm sorry I guess this is a silly question but I fail to run the example.

I cloned the repo just now. I went to src/html and ran python -m http.server then it said it failed to find the script bitmovinplayer-ui.js sp I created a directory called js and downloaded the file from http://cdn.bitmovin.com/player/web/8/bitmovinplayer-ui.js into that directory then I ran my python server and opened index.html but the loaded page is very messy and it doesn't do anything there are just many black boxes and buttons and texts in the screen. Here is what I get in browser console:

adaptive Video Streaming Service by www.bitmovin.com bitmovinplayer.js:11:1058786
Player Version 8.1.0 bitmovinplayer.js:11:1058786
source successfully loaded localhost:8000:264:7
XML Parsing Error: syntax error
Location: http://localhost:8000/
Line Number 1, Column 1:
localhost:8000:1:1
source successfully loaded localhost:8000:264:7 

I also tried to simply open the index.html file with firefox and it didn't work either. would you please be so kind as to explain to me step by step how I should run the examples?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.