Git Product home page Git Product logo

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 mariacrdribeiro 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

bitmovin-player-ui's Issues

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?

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.

ES6 exports

Replace the module.exports assignment with ES6 export statements.

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?).

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.

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

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

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

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.

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.

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

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.

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.

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"

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

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

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

[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

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

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.

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.

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

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.

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

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.

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!

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??

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.

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.

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.

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.

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.

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

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 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);

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.

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.