├── .babelrc ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .npmignore ├── .travis.yml ├── build ├── rollup.config.base.js ├── rollup.config.common.js ├── rollup.config.dev.js ├── rollup.config.es.js ├── rollup.config.min.js └── rollup.config.umd.js ├── demo ├── .DS_Store ├── base.js ├── get-live-url.js ├── hls-live │ ├── index.css │ └── index.html ├── hls │ ├── index.css │ └── index.html └── index.html ├── flow ├── base.js └── modules.js ├── karma.conf.js ├── lib ├── index.browser.js ├── index.js ├── index.min.js └── index.mjs ├── package.json ├── readme.md ├── rollup ├── src ├── .DS_Store ├── custom-config.js └── index.js └── tests └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "flow", 4 | [ 5 | "env", 6 | { 7 | "targets": { 8 | "browsers": [ 9 | "last 2 versions", 10 | "not ie <= 8" 11 | ] 12 | } 13 | } 14 | ], 15 | "stage-0" 16 | ], 17 | "plugins": [ 18 | "transform-decorators-legacy" 19 | ] 20 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | flow 4 | coverage 5 | bundle-size 6 | demo 7 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "process": true 4 | }, 5 | "env": { 6 | "browser": true, 7 | "commonjs": true, 8 | "es6": true 9 | }, 10 | "extends": [ 11 | "eslint-config-egg", 12 | "plugin:flowtype/recommended" 13 | ], 14 | "plugins": [ 15 | "flowtype" 16 | ], 17 | "parser": "babel-eslint", 18 | "parserOptions": { 19 | "sourceType": "module" 20 | }, 21 | "rules": { 22 | "valid-jsdoc": "off" 23 | } 24 | } -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/node_modules/.* 3 | .*/demos/.* 4 | .*/dist/.* 5 | [include] 6 | .*/src/.* 7 | [libs] 8 | flow 9 | node_modules/chimee-helper/lib/index.flow.js 10 | node_modules/chimee-kernel/lib/index.flow.js 11 | node_modules/toxic-decorators/lib/index.flow.js 12 | [lints] 13 | all=warn 14 | untyped-type-import=error 15 | sketchy-null-bool=off 16 | [options] 17 | esproposal.decorators=ignore 18 | [strict] 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | package-lock.json 61 | .DS_Store 62 | lib/index.dev.js 63 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | tests/ 2 | build/ 3 | lib/index.dev.js 4 | coverage/ 5 | demo/ 6 | doc/ 7 | flow/ 8 | node_modules/ 9 | tool/ 10 | bundle-size/ 11 | .babelrc 12 | .flowconfig 13 | .eslintignore 14 | .eslintrc 15 | karma.config.js 16 | src -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '8' 4 | script: 5 | - 'npm test' 6 | after_success: 7 | - 'npm install coveralls && npm install nyc && ./node_modules/.bin/nyc report --temp-directory=coverage --reporter=text-lcov | ./node_modules/.bin/coveralls' 8 | notifications: 9 | webhooks: 10 | urls: 11 | - 'https://www.travisbuddy.com/' 12 | on_success: never 13 | on_failure: always 14 | on_start: never 15 | on_cancel: never 16 | on_error: never 17 | -------------------------------------------------------------------------------- /build/rollup.config.base.js: -------------------------------------------------------------------------------- 1 | const { version, name, author, license, dependencies } = require('../package.json'); 2 | export const banner = ` 3 | /** 4 | * ${name} v${version} 5 | * (c) 2017-${(new Date()).getFullYear()} ${author} 6 | * Released under ${license} 7 | */ 8 | `; 9 | import babel from 'rollup-plugin-babel'; 10 | import resolve from 'rollup-plugin-node-resolve'; 11 | import commonjs from 'rollup-plugin-commonjs'; 12 | import replace from 'rollup-plugin-replace'; 13 | const babelConfig = { 14 | common: { 15 | presets: [ 16 | 'flow', 17 | [ 'env', { 18 | modules: false, 19 | targets: { 20 | browsers: [ 'last 2 versions', 'not ie <= 8' ], 21 | }, 22 | }], 23 | 'stage-0', 24 | ], 25 | exclude: 'node_modules/**', 26 | plugins: [ 27 | 'external-helpers', 28 | 'transform-decorators-legacy', 29 | 'transform-runtime', 30 | ], 31 | externalHelpers: true, 32 | runtimeHelpers: true, 33 | babelrc: false, 34 | }, 35 | es: { 36 | presets: [ 37 | 'flow', 38 | [ 'env', { 39 | modules: false, 40 | targets: { 41 | browsers: [ 'last 2 versions', 'not ie <= 8' ], 42 | }, 43 | }], 44 | 'stage-0', 45 | ], 46 | exclude: 'node_modules/**', 47 | plugins: [ 48 | 'external-helpers', 49 | 'transform-decorators-legacy', 50 | 'transform-runtime', 51 | ], 52 | externalHelpers: true, 53 | runtimeHelpers: true, 54 | babelrc: false, 55 | }, 56 | umd: { 57 | presets: [ 58 | 'flow', 59 | [ 'env', { 60 | modules: false, 61 | targets: { 62 | browsers: [ 'last 2 versions', 'not ie <= 8' ], 63 | }, 64 | }], 65 | 'stage-0', 66 | ], 67 | exclude: 'node_modules/**', 68 | plugins: [ 69 | 'external-helpers', 70 | 'transform-decorators-legacy', 71 | 'transform-runtime', 72 | ], 73 | externalHelpers: true, 74 | runtimeHelpers: true, 75 | babelrc: false, 76 | }, 77 | iife: { 78 | presets: [ 79 | 'flow', 80 | [ 'env', { 81 | modules: false, 82 | targets: { 83 | browsers: [ 'last 2 versions', 'not ie <= 8' ], 84 | }, 85 | }], 86 | 'stage-0', 87 | ], 88 | exclude: 'node_modules/**', 89 | plugins: [ 90 | 'external-helpers', 91 | 'transform-decorators-legacy', 92 | 'transform-runtime', 93 | ], 94 | externalHelpers: true, 95 | runtimeHelpers: true, 96 | babelrc: false, 97 | }, 98 | min: { 99 | presets: [ 100 | 'flow', 101 | [ 'env', { 102 | modules: false, 103 | targets: { 104 | browsers: [ 'last 2 versions', 'not ie <= 8' ], 105 | }, 106 | }], 107 | 'stage-0', 108 | ], 109 | exclude: 'node_modules/**', 110 | plugins: [ 111 | 'external-helpers', 112 | 'transform-decorators-legacy', 113 | ], 114 | runtimeHelpers: true, 115 | babelrc: false, 116 | }, 117 | }; 118 | // const externalRegExp = new RegExp(Object.keys(dependencies).concat(Object.keys(helperDependencies)).join('|')); 119 | const externalRegExp = new RegExp(Object.keys(dependencies).join('|')); 120 | export default function(mode) { 121 | return { 122 | input: 'src/index.js', 123 | external(id) { 124 | return !/min|umd|iife/.test(mode) && externalRegExp.test(id); 125 | }, 126 | plugins: [ 127 | babel(babelConfig[mode]), 128 | resolve({ 129 | customResolveOptions: { 130 | moduleDirectory: [ 'src', 'node_modules' ], 131 | }, 132 | preferBuiltins: true, 133 | }), 134 | commonjs(), 135 | replace({ 136 | 'process.env.VERSION': `'${version}'`, 137 | }), 138 | ].concat(/min|umd|iife/.test(mode) 139 | ? [ 140 | resolve({ 141 | customResolveOptions: { 142 | moduleDirectory: [ 'src', 'node_modules' ], 143 | }, 144 | preferBuiltins: true, 145 | }), 146 | ] 147 | : [] 148 | ), 149 | }; 150 | } 151 | -------------------------------------------------------------------------------- /build/rollup.config.common.js: -------------------------------------------------------------------------------- 1 | import base, { banner } from './rollup.config.base'; 2 | export default Object.assign(base('common'), { 3 | output: { 4 | banner, 5 | format: 'cjs', 6 | file: 'lib/index.js', 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /build/rollup.config.dev.js: -------------------------------------------------------------------------------- 1 | import base, { banner } from './rollup.config.base'; 2 | import serve from 'rollup-plugin-serve'; 3 | import livereload from 'rollup-plugin-livereload'; 4 | import replace from 'rollup-plugin-replace'; 5 | import { camelize } from 'toxic-utils'; 6 | const { name } = require('../package.json'); 7 | const config = base('iife'); 8 | config.plugins.push( 9 | serve(), 10 | livereload() 11 | ); 12 | config.plugins.unshift(replace({ 13 | 'process.env.NODE_ENV': '"development"', 14 | })); 15 | export default Object.assign(config, { 16 | output: { 17 | banner, 18 | format: 'umd', 19 | file: 'lib/index.dev.js', 20 | name: camelize(name, true), 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /build/rollup.config.es.js: -------------------------------------------------------------------------------- 1 | import base, { banner } from './rollup.config.base'; 2 | export default Object.assign(base('es'), { 3 | output: { 4 | banner, 5 | format: 'es', 6 | file: 'lib/index.mjs', 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /build/rollup.config.min.js: -------------------------------------------------------------------------------- 1 | import base, { banner } from './rollup.config.base'; 2 | import { uglify } from 'rollup-plugin-uglify'; 3 | import replace from 'rollup-plugin-replace'; 4 | const { name } = require('../package.json'); 5 | import { camelize } from 'toxic-utils'; 6 | const config = base('min'); 7 | config.plugins.unshift(replace({ 8 | 'process.env.NODE_ENV': '"production"', 9 | })); 10 | config.plugins.push(uglify({})); 11 | export default Object.assign(config, { 12 | output: { 13 | banner, 14 | format: 'umd', 15 | file: 'lib/index.min.js', 16 | name: camelize(name, true), 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /build/rollup.config.umd.js: -------------------------------------------------------------------------------- 1 | import base, { banner } from './rollup.config.base'; 2 | const { name } = require('../package.json'); 3 | import { camelize } from 'toxic-utils'; 4 | import replace from 'rollup-plugin-replace'; 5 | const config = base('umd'); 6 | config.plugins.unshift(replace({ 7 | 'process.env.NODE_ENV': '"development"', 8 | })); 9 | export default Object.assign(config, { 10 | output: { 11 | banner, 12 | format: 'umd', 13 | file: 'lib/index.browser.js', 14 | name: camelize(name, true), 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /demo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chimeejs/chimee-kernel-hls/e09bed717bf7bc62086642120e48b5975d3c89be/demo/.DS_Store -------------------------------------------------------------------------------- /demo/base.js: -------------------------------------------------------------------------------- 1 | // mp4 http://cdn.toxicjohann.com/lostStar.mp4 2 | // hls http://yunxianchang.live.ujne7.com/vod-system-bj/44_176_20170224113626af3a75cd-3508-4bc3-b51f-366fca3c7e39.m3u8 3 | // flv直播 http://pf.live.360vcloud.net/live_customers3/6818c55761856069a0ce 4 | // flv直播 http://flv.jia.360.cn/live_jia_public/_LC_RE_non_3605375765815007736131516144_BX.flv 5 | // flv点播 http://yunxianchang.live.ujne7.com/vod-system-bj/TL1ce1196bce348070bfeef2116efbdea6.flv 6 | // flv点播 http://yunxianchang.live.ujne7.com/vod-system-bj/TL2791e64b69ea0bea234c284c694986aa.flv 7 | window.start = function() { 8 | const kernelConfig = window.kernelConfig || {}; 9 | const player = document.querySelector('#player'); 10 | const kernel = new window.ChimeeKernel(player, kernelConfig); 11 | window.kernel = kernel; 12 | 13 | const seekController = document.createElement('div'); 14 | seekController.innerText = 'seek: '; 15 | 16 | const seekInput = document.createElement('input'); 17 | seekInput.value = 0; 18 | seekInput.type = 'number'; 19 | 20 | seekController.appendChild(seekInput); 21 | 22 | document.body.appendChild(seekController); 23 | 24 | const srcController = document.createElement('div'); 25 | srcController.innerText = 'src: '; 26 | 27 | const srcInput = document.createElement('input'); 28 | srcInput.value = ''; 29 | srcInput.type = 'text'; 30 | 31 | srcController.appendChild(srcInput); 32 | 33 | document.body.appendChild(srcController); 34 | 35 | const keys = [ 'play', 'pause', 'load', 'startLoad', 'stopLoad', 'attachMedia', 'seek', 'refresh', 'destroy' ]; 36 | const controller = document.createElement('div'); 37 | keys.forEach(function(key) { 38 | const button = document.createElement('button'); 39 | button.innerText = key; 40 | button.addEventListener('click', function() { 41 | if (key === 'seek') { 42 | kernel.seek(parseFloat(seekInput.value)); 43 | return; 44 | } 45 | if (key === 'load') { 46 | kernel.load(srcInput.value); 47 | return; 48 | } 49 | kernel[key](); 50 | }); 51 | controller.appendChild(button); 52 | }); 53 | 54 | document.body.appendChild(controller); 55 | 56 | kernel.load(); 57 | }; 58 | -------------------------------------------------------------------------------- /demo/get-live-url.js: -------------------------------------------------------------------------------- 1 | const $ = window.$; 2 | 3 | window.getLiveSource = function(type) { 4 | const sources = {}; 5 | 6 | // 取个SD的直播流来用用 7 | function getSDLiveUrl(sn) { 8 | const a = 've3.ji'; 9 | const b = '60.c'; 10 | return $.ajax({ 11 | url: 'https://li' + a + 'a.3' + b + 'n/public/getInfoAndPlayV2?from=mpc_ipcam_web&sn=36' + sn + '&taskid=' + +new Date(), 12 | type: 'get', 13 | dataType: 'jsonp', 14 | }).then(function(data) { 15 | let liveHLS = data && data.playInfo && data.playInfo.hls; 16 | const ret = {}; 17 | if (liveHLS) { 18 | if (type === 'flv') liveHLS = liveHLS.replace('hls-live', 'flv-live').replace('/index.m3u8', '.flv'); 19 | ret.url = liveHLS; 20 | ret.poster = data.publicInfo.thumbnail; 21 | } 22 | return ret; 23 | }); 24 | } 25 | 26 | return Promise.all([ 27 | getSDLiveUrl('072754052'), 28 | getSDLiveUrl('0K0905701'), 29 | getSDLiveUrl('0K0904122'), 30 | ]).then(function(re) { 31 | if (!re[0].url || !re[1].url || !re[2].url) { 32 | console.error('流地址异常'); 33 | } 34 | sources.snow = re[0].url; 35 | sources.river = re[1].url; 36 | sources.city = re[2].url; 37 | return sources; 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /demo/hls-live/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | html { 7 | background-color: #FFFBE6; 8 | font-family: "Oswald", "HelveticaNeue-CondensedBold", "Arial Narrow", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; 9 | background-repeat: no-repeat; 10 | min-height: 100%; 11 | } 12 | body { 13 | padding: 10px; 14 | box-sizing: border-box; 15 | color: #36384A; 16 | max-width: 800px; 17 | margin: auto; 18 | } 19 | #wrapper { 20 | position: relative; 21 | width: 100%; 22 | height: 100%; 23 | } 24 | container { 25 | position: relative; 26 | display: block; 27 | /* width: 100%; 28 | height: 100%; */ 29 | } 30 | video { 31 | /* width: 100%; 32 | height: 100%; */ 33 | display: block; 34 | background-color: #000; 35 | } 36 | video:focus, 37 | video:active { 38 | outline: none; 39 | } 40 | button { 41 | color: #fff; 42 | background-color: #3F4F68; 43 | padding: 6px 12px; 44 | text-decoration: none; 45 | -webkit-user-select: none; 46 | -moz-user-select: none; 47 | -ms-user-select: none; 48 | user-select: none; 49 | border-radius: 4px; 50 | text-transform: none; 51 | outline: none; 52 | border: none; 53 | margin-bottom: 2px; 54 | } 55 | h1 { 56 | color: #9D295A; 57 | } 58 | button:active { 59 | background-color: #36384A; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /demo/hls-live/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | hls test demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

hls Demo

14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 32 | 33 | -------------------------------------------------------------------------------- /demo/hls/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | html { 7 | background-color: #FFFBE6; 8 | font-family: "Oswald", "HelveticaNeue-CondensedBold", "Arial Narrow", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; 9 | background-repeat: no-repeat; 10 | min-height: 100%; 11 | } 12 | body { 13 | padding: 10px; 14 | box-sizing: border-box; 15 | color: #36384A; 16 | max-width: 800px; 17 | margin: auto; 18 | } 19 | #wrapper { 20 | position: relative; 21 | width: 100%; 22 | height: 100%; 23 | } 24 | container { 25 | position: relative; 26 | display: block; 27 | /* width: 100%; 28 | height: 100%; */ 29 | } 30 | video { 31 | /* width: 100%; 32 | height: 100%; */ 33 | display: block; 34 | background-color: #000; 35 | } 36 | video:focus, 37 | video:active { 38 | outline: none; 39 | } 40 | button { 41 | color: #fff; 42 | background-color: #3F4F68; 43 | padding: 6px 12px; 44 | text-decoration: none; 45 | -webkit-user-select: none; 46 | -moz-user-select: none; 47 | -ms-user-select: none; 48 | user-select: none; 49 | border-radius: 4px; 50 | text-transform: none; 51 | outline: none; 52 | border: none; 53 | margin-bottom: 2px; 54 | } 55 | h1 { 56 | color: #9D295A; 57 | } 58 | button:active { 59 | background-color: #36384A; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /demo/hls/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | hls test demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

hls Demo

14 |
15 | 16 | 17 | 18 | 19 | 20 | 38 | 39 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 38 | 39 | -------------------------------------------------------------------------------- /flow/base.js: -------------------------------------------------------------------------------- 1 | import type CustomConfig from '../src/custom-config.js'; 2 | 3 | -------------------------------------------------------------------------------- /flow/modules.js: -------------------------------------------------------------------------------- 1 | declare module 'hls.js' { 2 | declare module.exports: any; 3 | } 4 | 5 | declare module 'toxic-decorators' { 6 | declare module.exports: any; 7 | } -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // process.env.CHROME_BIN = require('puppeteer').executablePath(); 2 | const { version, name } = require('./package.json'); 3 | const { camelize } = require('toxic-utils'); 4 | 5 | module.exports = function(config) { 6 | config.set({ 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | // frameworks to use 11 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 12 | frameworks: [ 'mocha' ], 13 | 14 | // list of files / patterns to load in the browser 15 | files: [ 16 | 'tests/**/*.js', 17 | ], 18 | 19 | // list of files to exclude 20 | exclude: [], 21 | 22 | // preprocess matching files before serving them to the browser 23 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 24 | preprocessors: { 25 | 'tests/**/*.js': [ 'rollup' ], 26 | 'src/**/*.js': [ 'coverage' ], 27 | }, 28 | 29 | // test results reporter to use 30 | // possible values: 'dots', 'progress' 31 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 32 | reporters: [ 'mocha', 'coverage-istanbul', 'progress', 'coverage', 'coveralls' ], 33 | 34 | coverageIstanbulReporter: { 35 | reports: [ 'lcov', 'text-summary' ], 36 | }, 37 | 38 | coverageReporter: { 39 | type: 'lcov', 40 | dir: 'coverage/', 41 | }, 42 | 43 | rollupPreprocessor: { 44 | plugins: [ 45 | require('rollup-plugin-babel')({ 46 | presets: [ 47 | 'flow', 48 | [ 'env', { 49 | modules: false, 50 | targets: { 51 | browsers: [ 'last 2 versions', 'not ie <= 8' ], 52 | }, 53 | }], 54 | 'stage-0', 55 | ], 56 | exclude: 'node_modules/**', 57 | plugins: [ 58 | 'istanbul', 59 | 'external-helpers', 60 | 'transform-decorators-legacy', 61 | 'transform-runtime', 62 | ], 63 | externalHelpers: true, 64 | runtimeHelpers: true, 65 | babelrc: false, 66 | }), 67 | require('rollup-plugin-flow-no-whitespace')(), 68 | require('rollup-plugin-node-resolve')({ 69 | customResolveOptions: { 70 | moduleDirectory: [ 'src', 'node_modules' ], 71 | }, 72 | }), 73 | require('rollup-plugin-commonjs')(), 74 | require('rollup-plugin-replace')({ 75 | 'process.env.VERSION': `'${version}'`, 76 | 'process.env.TRAVIS': `${process.env.TRAVIS}`, 77 | }), 78 | ], 79 | output: { 80 | format: 'iife', // Helps prevent naming collisions. 81 | name: camelize(name), // Required for 'iife' format. 82 | }, 83 | sourcemap: 'inline', // Sensible for testing. 84 | }, 85 | 86 | // web server port 87 | port: 9876, 88 | 89 | // enable / disable colors in the output (reporters and logs) 90 | // colors: true, 91 | 92 | // level of logging 93 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 94 | logLevel: config.LOG_DEBUG, 95 | 96 | // enable / disable watching file and executing tests whenever any file changes 97 | autoWatch: false, 98 | 99 | // start these browsers 100 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 101 | browsers: [ 'FirefoxHeadless' ], 102 | 103 | customLaunchers: { 104 | FirefoxHeadless: { 105 | base: 'Firefox', 106 | flags: [ '-headless' ], 107 | }, 108 | }, 109 | 110 | // Continuous Integration mode 111 | // if true, Karma captures browsers, runs the tests and exits 112 | singleRun: true, 113 | 114 | // Concurrency level 115 | // how many browser should be started simultaneous 116 | concurrency: Infinity, 117 | }); 118 | }; 119 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * chimee-kernel-hls v1.3.2 4 | * (c) 2017-2018 songguangyu 5 | * Released under MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } 11 | 12 | var _Object$getOwnPropertyDescriptor = _interopDefault(require('babel-runtime/core-js/object/get-own-property-descriptor')); 13 | var _typeof = _interopDefault(require('babel-runtime/helpers/typeof')); 14 | var _Object$getPrototypeOf = _interopDefault(require('babel-runtime/core-js/object/get-prototype-of')); 15 | var _classCallCheck = _interopDefault(require('babel-runtime/helpers/classCallCheck')); 16 | var _possibleConstructorReturn = _interopDefault(require('babel-runtime/helpers/possibleConstructorReturn')); 17 | var _createClass = _interopDefault(require('babel-runtime/helpers/createClass')); 18 | var _inherits = _interopDefault(require('babel-runtime/helpers/inherits')); 19 | var HlsCore = _interopDefault(require('hls.js')); 20 | var chimeeHelper = require('chimee-helper'); 21 | var toxicDecorators = require('toxic-decorators'); 22 | 23 | var defaultCustomConfig = { 24 | debug: false, 25 | enableWorker: true 26 | }; 27 | 28 | var _class; 29 | 30 | function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { 31 | var desc = {}; 32 | Object['ke' + 'ys'](descriptor).forEach(function (key) { 33 | desc[key] = descriptor[key]; 34 | }); 35 | desc.enumerable = !!desc.enumerable; 36 | desc.configurable = !!desc.configurable; 37 | 38 | if ('value' in desc || desc.initializer) { 39 | desc.writable = true; 40 | } 41 | 42 | desc = decorators.slice().reverse().reduce(function (desc, decorator) { 43 | return decorator(target, property, desc) || desc; 44 | }, desc); 45 | 46 | if (context && desc.initializer !== void 0) { 47 | desc.value = desc.initializer ? desc.initializer.call(context) : void 0; 48 | desc.initializer = undefined; 49 | } 50 | 51 | if (desc.initializer === void 0) { 52 | Object['define' + 'Property'](target, property, desc); 53 | desc = null; 54 | } 55 | 56 | return desc; 57 | } 58 | 59 | var LOG_TAG = 'chimee-kernel-hls'; 60 | 61 | var Hls = (_class = function (_CustEvent) { 62 | _inherits(Hls, _CustEvent); 63 | 64 | _createClass(Hls, null, [{ 65 | key: 'isSupport', 66 | value: function isSupport() { 67 | return HlsCore.isSupported(); 68 | } 69 | }]); 70 | 71 | function Hls(videoElement, config) { 72 | var customConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 73 | 74 | _classCallCheck(this, Hls); 75 | 76 | var _this = _possibleConstructorReturn(this, (Hls.__proto__ || _Object$getPrototypeOf(Hls)).call(this)); 77 | 78 | _this.version = '1.3.2'; 79 | 80 | if (!chimeeHelper.isElement(videoElement)) throw new Error('video element passed in ' + LOG_TAG + ' must be a HTMLVideoElement, but not ' + (typeof videoElement === 'undefined' ? 'undefined' : _typeof(videoElement))); 81 | if (!chimeeHelper.isObject(config)) throw new Error('config of ' + LOG_TAG + ' must be an Object but not ' + (typeof config === 'undefined' ? 'undefined' : _typeof(config))); 82 | _this.video = videoElement; 83 | _this.config = config; 84 | _this.customConfig = chimeeHelper.deepAssign({}, defaultCustomConfig, customConfig); 85 | _this.hlsKernel = new HlsCore(_this.customConfig); 86 | _this.bindEvents(); 87 | _this.attachMedia(); 88 | return _this; 89 | } 90 | 91 | _createClass(Hls, [{ 92 | key: 'bindEvents', 93 | value: function bindEvents() { 94 | var remove = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; 95 | 96 | var hlsKernel = this.hlsKernel; 97 | /* istanbul ignore else */ 98 | if (hlsKernel) { 99 | hlsKernel[remove ? 'off' : 'on'](HlsCore.Events.ERROR, this.hlsErrorHandler); 100 | } 101 | } 102 | }, { 103 | key: 'load', 104 | value: function load() { 105 | return this.hlsKernel.loadSource(this.config.src); 106 | } 107 | }, { 108 | key: 'startLoad', 109 | value: function startLoad() { 110 | return this.hlsKernel.startLoad(); 111 | } 112 | }, { 113 | key: 'stopLoad', 114 | value: function stopLoad() { 115 | return this.hlsKernel.stopLoad(); 116 | } 117 | }, { 118 | key: 'attachMedia', 119 | value: function attachMedia() { 120 | return this.hlsKernel.attachMedia(this.video); 121 | } 122 | }, { 123 | key: 'play', 124 | value: function play() { 125 | return this.video.play(); 126 | } 127 | }, { 128 | key: 'destroy', 129 | value: function destroy() { 130 | this.bindEvents(true); 131 | return this.hlsKernel.destroy(); 132 | } 133 | }, { 134 | key: 'seek', 135 | value: function seek(seconds) { 136 | this.video.currentTime = seconds; 137 | } 138 | }, { 139 | key: 'pause', 140 | value: function pause() { 141 | return this.video.pause(); 142 | } 143 | }, { 144 | key: 'refresh', 145 | value: function refresh() { 146 | this.hlsKernel.stopLoad(); 147 | return this.hlsKernel.loadSource(this.config.src); 148 | } 149 | }, { 150 | key: 'hlsErrorHandler', 151 | value: function hlsErrorHandler(event, data) { 152 | this.emit('error', data); 153 | this.emit(event, data); 154 | /* istanbul ignore next */ 155 | chimeeHelper.Log.error(LOG_TAG + (event ? ' ' + event : ''), data.details); 156 | } 157 | }]); 158 | 159 | return Hls; 160 | }(chimeeHelper.CustEvent), (_applyDecoratedDescriptor(_class.prototype, 'hlsErrorHandler', [toxicDecorators.autobind], _Object$getOwnPropertyDescriptor(_class.prototype, 'hlsErrorHandler'), _class.prototype)), _class); 161 | 162 | module.exports = Hls; 163 | -------------------------------------------------------------------------------- /lib/index.mjs: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * chimee-kernel-hls v1.3.2 4 | * (c) 2017-2018 songguangyu 5 | * Released under MIT 6 | */ 7 | 8 | import _Object$getOwnPropertyDescriptor from 'babel-runtime/core-js/object/get-own-property-descriptor'; 9 | import _typeof from 'babel-runtime/helpers/typeof'; 10 | import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of'; 11 | import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; 12 | import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; 13 | import _createClass from 'babel-runtime/helpers/createClass'; 14 | import _inherits from 'babel-runtime/helpers/inherits'; 15 | import HlsCore from 'hls.js'; 16 | import { CustEvent, deepAssign, Log, isElement, isObject } from 'chimee-helper'; 17 | import { autobind } from 'toxic-decorators'; 18 | 19 | var defaultCustomConfig = { 20 | debug: false, 21 | enableWorker: true 22 | }; 23 | 24 | var _class; 25 | 26 | function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { 27 | var desc = {}; 28 | Object['ke' + 'ys'](descriptor).forEach(function (key) { 29 | desc[key] = descriptor[key]; 30 | }); 31 | desc.enumerable = !!desc.enumerable; 32 | desc.configurable = !!desc.configurable; 33 | 34 | if ('value' in desc || desc.initializer) { 35 | desc.writable = true; 36 | } 37 | 38 | desc = decorators.slice().reverse().reduce(function (desc, decorator) { 39 | return decorator(target, property, desc) || desc; 40 | }, desc); 41 | 42 | if (context && desc.initializer !== void 0) { 43 | desc.value = desc.initializer ? desc.initializer.call(context) : void 0; 44 | desc.initializer = undefined; 45 | } 46 | 47 | if (desc.initializer === void 0) { 48 | Object['define' + 'Property'](target, property, desc); 49 | desc = null; 50 | } 51 | 52 | return desc; 53 | } 54 | 55 | var LOG_TAG = 'chimee-kernel-hls'; 56 | 57 | var Hls = (_class = function (_CustEvent) { 58 | _inherits(Hls, _CustEvent); 59 | 60 | _createClass(Hls, null, [{ 61 | key: 'isSupport', 62 | value: function isSupport() { 63 | return HlsCore.isSupported(); 64 | } 65 | }]); 66 | 67 | function Hls(videoElement, config) { 68 | var customConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 69 | 70 | _classCallCheck(this, Hls); 71 | 72 | var _this = _possibleConstructorReturn(this, (Hls.__proto__ || _Object$getPrototypeOf(Hls)).call(this)); 73 | 74 | _this.version = '1.3.2'; 75 | 76 | if (!isElement(videoElement)) throw new Error('video element passed in ' + LOG_TAG + ' must be a HTMLVideoElement, but not ' + (typeof videoElement === 'undefined' ? 'undefined' : _typeof(videoElement))); 77 | if (!isObject(config)) throw new Error('config of ' + LOG_TAG + ' must be an Object but not ' + (typeof config === 'undefined' ? 'undefined' : _typeof(config))); 78 | _this.video = videoElement; 79 | _this.config = config; 80 | _this.customConfig = deepAssign({}, defaultCustomConfig, customConfig); 81 | _this.hlsKernel = new HlsCore(_this.customConfig); 82 | _this.bindEvents(); 83 | _this.attachMedia(); 84 | return _this; 85 | } 86 | 87 | _createClass(Hls, [{ 88 | key: 'bindEvents', 89 | value: function bindEvents() { 90 | var remove = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; 91 | 92 | var hlsKernel = this.hlsKernel; 93 | /* istanbul ignore else */ 94 | if (hlsKernel) { 95 | hlsKernel[remove ? 'off' : 'on'](HlsCore.Events.ERROR, this.hlsErrorHandler); 96 | } 97 | } 98 | }, { 99 | key: 'load', 100 | value: function load() { 101 | return this.hlsKernel.loadSource(this.config.src); 102 | } 103 | }, { 104 | key: 'startLoad', 105 | value: function startLoad() { 106 | return this.hlsKernel.startLoad(); 107 | } 108 | }, { 109 | key: 'stopLoad', 110 | value: function stopLoad() { 111 | return this.hlsKernel.stopLoad(); 112 | } 113 | }, { 114 | key: 'attachMedia', 115 | value: function attachMedia() { 116 | return this.hlsKernel.attachMedia(this.video); 117 | } 118 | }, { 119 | key: 'play', 120 | value: function play() { 121 | return this.video.play(); 122 | } 123 | }, { 124 | key: 'destroy', 125 | value: function destroy() { 126 | this.bindEvents(true); 127 | return this.hlsKernel.destroy(); 128 | } 129 | }, { 130 | key: 'seek', 131 | value: function seek(seconds) { 132 | this.video.currentTime = seconds; 133 | } 134 | }, { 135 | key: 'pause', 136 | value: function pause() { 137 | return this.video.pause(); 138 | } 139 | }, { 140 | key: 'refresh', 141 | value: function refresh() { 142 | this.hlsKernel.stopLoad(); 143 | return this.hlsKernel.loadSource(this.config.src); 144 | } 145 | }, { 146 | key: 'hlsErrorHandler', 147 | value: function hlsErrorHandler(event, data) { 148 | this.emit('error', data); 149 | this.emit(event, data); 150 | /* istanbul ignore next */ 151 | Log.error(LOG_TAG + (event ? ' ' + event : ''), data.details); 152 | } 153 | }]); 154 | 155 | return Hls; 156 | }(CustEvent), (_applyDecoratedDescriptor(_class.prototype, 'hlsErrorHandler', [autobind], _Object$getOwnPropertyDescriptor(_class.prototype, 'hlsErrorHandler'), _class.prototype)), _class); 157 | 158 | export default Hls; 159 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chimee-kernel-hls", 3 | "version": "1.3.2", 4 | "description": "kernel-hls of chimee", 5 | "main": "lib/index.js", 6 | "module": "lib/index.mjs", 7 | "jsnext:main": "lib/index.mjs", 8 | "browser": "lib/index.browser.js", 9 | "scripts": { 10 | "precommit": "npm run lint", 11 | "prepush": "npm run test", 12 | "prepublishOnly": "npm run lint && npm t && pkg-ok", 13 | "build": "npm run b-common && npm run b-es && npm run b-umd && npm run b-min", 14 | "b-common": "rollup -c build/rollup.config.common.js", 15 | "b-es": "rollup -c build/rollup.config.es.js", 16 | "b-umd": "rollup -c build/rollup.config.umd.js", 17 | "b-min": "rollup -c build/rollup.config.min.js", 18 | "start": "rollup -c build/rollup.config.dev.js -w", 19 | "lint": "eslint . --fix && flow check", 20 | "flow": "flow check", 21 | "test": "karma start karma.conf.js", 22 | "unit": "karma start karma.conf.js --auto-watch" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/Chimeejs/chimee-kernel-hls.git" 27 | }, 28 | "keywords": [ 29 | "kernel", 30 | "chimee", 31 | "video", 32 | "hls" 33 | ], 34 | "author": "songguangyu", 35 | "license": "MIT", 36 | "bugs": { 37 | "url": "https://github.com/Chimeejs/chimee-kernel-hls/issues" 38 | }, 39 | "homepage": "https://github.com/Chimeejs/chimee-kernel-hls#readme", 40 | "dependencies": { 41 | "babel-runtime": "^6.26.0", 42 | "chimee-helper": "^0.2.11", 43 | "hls.js": "^0.9.1", 44 | "toxic-decorators": "^0.3.8" 45 | }, 46 | "devDependencies": { 47 | "babel-core": "^6.26.3", 48 | "babel-eslint": "^8.2.3", 49 | "babel-plugin-istanbul": "^4.1.6", 50 | "babel-plugin-transform-decorators-legacy": "^1.3.5", 51 | "babel-plugin-transform-runtime": "^6.23.0", 52 | "babel-preset-env": "^1.7.0", 53 | "babel-preset-es2015-rollup": "^3.0.0", 54 | "babel-preset-flow": "^6.23.0", 55 | "babel-preset-latest": "^6.24.1", 56 | "babel-preset-stage-0": "^6.24.1", 57 | "chai": "^4.1.2", 58 | "chimee-kernel": "^1.4.0", 59 | "eslint": "^4.19.1", 60 | "eslint-config-egg": "^7.0.0", 61 | "eslint-plugin-flowtype": "^2.49.3", 62 | "flow-bin": "^0.73.0", 63 | "husky": "^0.14.3", 64 | "karma": "^2.0.2", 65 | "karma-coverage": "^1.1.2", 66 | "karma-coverage-istanbul-reporter": "^2.0.1", 67 | "karma-coveralls": "^1.2.1", 68 | "karma-firefox-launcher": "^1.1.0", 69 | "karma-mocha": "^1.3.0", 70 | "karma-mocha-reporter": "^2.2.5", 71 | "karma-rollup-preprocessor": "^6.0.0", 72 | "karma-sourcemap-loader": "^0.3.7", 73 | "mocha": "^5.2.0", 74 | "pkg-ok": "^2.2.0", 75 | "puppeteer": "^1.4.0", 76 | "rollup": "^0.59.4", 77 | "rollup-plugin-babel": "^3.0.4", 78 | "rollup-plugin-commonjs": "^9.1.3", 79 | "rollup-plugin-flow-no-whitespace": "^1.0.0", 80 | "rollup-plugin-includepaths": "^0.2.2", 81 | "rollup-plugin-livereload": "^0.6.0", 82 | "rollup-plugin-node-resolve": "^3.3.0", 83 | "rollup-plugin-replace": "^2.0.0", 84 | "rollup-plugin-serve": "^0.4.2", 85 | "rollup-plugin-uglify": "^4.0.0", 86 | "rollup-watch": "^4.3.1" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # chimee-kernel-hls 2 | 3 | [![Build Status](https://img.shields.io/travis/Chimeejs/chimee-kernel-hls/master.svg?style=flat-square)](https://travis-ci.org/Chimeejs/chimee-kernel-hls.svg?branch=master) 4 | [![Coverage Status](https://img.shields.io/coveralls/Chimeejs/chimee-kernel-hls/master.svg?style=flat-square)](https://coveralls.io/github/Chimeejs/chimee-kernel-hls?branch=master) 5 | [![npm](https://img.shields.io/npm/v/chimee-kernel-hls.svg?colorB=brightgreen&style=flat-square)](https://www.npmjs.com/package/chimee-kernel-hls) 6 | [![dependency Status](https://david-dm.org/Chimeejs/chimee-kernel-hls.svg)](https://david-dm.org/Chimeejs/chimee-kernel-hls) 7 | [![devDependency Status](https://david-dm.org/Chimeejs/chimee-kernel-hls/dev-status.svg)](https://david-dm.org/Chimeejs/chimee-kernel-hls?type=dev) 8 | 9 | chimee-kernel-hls is the decoder for [chimee](https://github.com/Chimeejs/chimee). It can decode m3u8 on browser. 10 | 11 | It's based on [hls.js](https://github.com/video-dev/hls.js). 12 | 13 | It totally fit the requirement of [chimee-kernel](https://github.com/Chimeejs/chimee-kernel). 14 | 15 | It should only be used in the PC, as most of mobile browser support m3u8. 16 | 17 | ## Installation 18 | ``` 19 | npm install --save chimee-kernel-hls 20 | ``` 21 | ## Usage 22 | 23 | You can use chimee-kernel-hls in chimee or chimee-player like this. 24 | 25 | ```javascript 26 | import Chimee from 'chimee'; 27 | import ChimeeKernelHls from 'chimee-kernel-hls'; 28 | const chimee = new Chimee({ 29 | wrapper: '#wrapper', 30 | src: 'http://cdn.toxicjohann.com/lostStar.mp4', 31 | controls: true, 32 | autoplay: true, 33 | kernels: { 34 | hls: ChimeeKernelHls, 35 | } 36 | }); 37 | chimee.play(); 38 | ``` 39 | 40 | We also support custom config on hls.js, such as config describe in the [document](https://github.com/video-dev/hls.js/blob/master/doc/API.md#fine-tuning). 41 | 42 | ```Javascript 43 | import Chimee from 'chimee'; 44 | import ChimeeKernelHls from 'chimee-kernel-hls'; 45 | const chimee = new Chimee({ 46 | wrapper: '#wrapper', 47 | src: 'http://cdn.toxicjohann.com/lostStar.mp4', 48 | controls: true, 49 | autoplay: true, 50 | kernels: { 51 | hls: { 52 | handler: ChimeeKernelHls, 53 | debug: true, 54 | } 55 | } 56 | }); 57 | chimee.play(); 58 | ``` -------------------------------------------------------------------------------- /rollup: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chimeejs/chimee-kernel-hls/e09bed717bf7bc62086642120e48b5975d3c89be/rollup -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chimeejs/chimee-kernel-hls/e09bed717bf7bc62086642120e48b5975d3c89be/src/.DS_Store -------------------------------------------------------------------------------- /src/custom-config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | debug: false, 3 | enableWorker: true, 4 | }; 5 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import HlsCore from 'hls.js'; 3 | import { CustEvent, deepAssign, Log, isElement, isObject } from 'chimee-helper'; 4 | import defaultCustomConfig from './custom-config.js'; 5 | import { autobind } from 'toxic-decorators'; 6 | 7 | const LOG_TAG = 'chimee-kernel-hls'; 8 | 9 | export default class Hls extends CustEvent { 10 | version: string; 11 | video: HTMLVideoElement; 12 | config: KernelConfig; 13 | customConfig: CustomConfig; 14 | version = process.env.VERSION; 15 | hlsKernel: any 16 | 17 | static isSupport() { 18 | return HlsCore.isSupported(); 19 | } 20 | 21 | constructor(videoElement: HTMLVideoElement, config: KernelConfig, customConfig: CustomConfig = {}) { 22 | super(); 23 | if (!isElement(videoElement)) throw new Error(`video element passed in ${LOG_TAG} must be a HTMLVideoElement, but not ${typeof videoElement}`); 24 | if (!isObject(config)) throw new Error(`config of ${LOG_TAG} must be an Object but not ${typeof config}`); 25 | this.video = videoElement; 26 | this.config = config; 27 | this.customConfig = deepAssign({}, defaultCustomConfig, customConfig); 28 | this.hlsKernel = new HlsCore(this.customConfig); 29 | this.bindEvents(); 30 | this.attachMedia(); 31 | } 32 | 33 | bindEvents(remove: boolean = false) { 34 | const hlsKernel = this.hlsKernel; 35 | /* istanbul ignore else */ 36 | if (hlsKernel) { 37 | hlsKernel[remove ? 'off' : 'on'](HlsCore.Events.ERROR, this.hlsErrorHandler); 38 | } 39 | } 40 | 41 | load() { 42 | return this.hlsKernel.loadSource(this.config.src); 43 | } 44 | 45 | startLoad() { 46 | return this.hlsKernel.startLoad(); 47 | } 48 | 49 | stopLoad() { 50 | return this.hlsKernel.stopLoad(); 51 | } 52 | 53 | attachMedia() { 54 | return this.hlsKernel.attachMedia(this.video); 55 | } 56 | 57 | play() { 58 | return this.video.play(); 59 | } 60 | 61 | destroy() { 62 | this.bindEvents(true); 63 | return this.hlsKernel.destroy(); 64 | } 65 | 66 | seek(seconds: number) { 67 | this.video.currentTime = seconds; 68 | } 69 | 70 | pause() { 71 | return this.video.pause(); 72 | } 73 | 74 | refresh() { 75 | this.hlsKernel.stopLoad(); 76 | return this.hlsKernel.loadSource(this.config.src); 77 | } 78 | 79 | @autobind 80 | hlsErrorHandler(event: string, data: Object) { 81 | this.emit('error', data); 82 | this.emit(event, data); 83 | /* istanbul ignore next */ 84 | Log.error(LOG_TAG + (event ? ' ' + event : ''), data.details); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/index.js: -------------------------------------------------------------------------------- 1 | import ChimeeKernelHls from '../src/index'; 2 | import chai from 'chai'; 3 | import { isFunction } from 'chimee-helper'; 4 | const { expect } = chai; 5 | describe('chimee-kernel base requirement', () => { 6 | let videoElement; 7 | beforeEach(() => { 8 | videoElement = document.createElement('video'); 9 | }); 10 | afterEach(() => { 11 | videoElement = null; 12 | }); 13 | it('isSupport', () => { 14 | expect(ChimeeKernelHls.isSupport()).to.equal(!process.env.TRAVIS); 15 | }); 16 | it('base method', () => { 17 | const config = { 18 | src: 'https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8', 19 | box: 'hls', 20 | isLive: false, 21 | }; 22 | const kernel = new ChimeeKernelHls(videoElement, config, { 23 | debug: true, 24 | }); 25 | expect(kernel.config).to.deep.equal(config); 26 | expect(kernel.video).to.equal(videoElement); 27 | expect(isFunction(kernel.load)).to.equal(true); 28 | expect(isFunction(kernel.play)).to.equal(true); 29 | expect(isFunction(kernel.pause)).to.equal(true); 30 | expect(isFunction(kernel.refresh)).to.equal(true); 31 | expect(isFunction(kernel.attachMedia)).to.equal(true); 32 | expect(isFunction(kernel.seek)).to.equal(true); 33 | expect(isFunction(kernel.destroy)).to.equal(true); 34 | expect(isFunction(kernel.on)).to.equal(true); 35 | expect(isFunction(kernel.off)).to.equal(true); 36 | expect(isFunction(kernel.once)).to.equal(true); 37 | expect(isFunction(kernel.emit)).to.equal(true); 38 | kernel.destroy(); 39 | }); 40 | }); 41 | 42 | describe('method it', () => { 43 | let kernel; 44 | let config; 45 | let videoElement; 46 | beforeEach(() => { 47 | videoElement = document.createElement('video'); 48 | config = { 49 | src: 'https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8', 50 | box: 'hls', 51 | isLive: false, 52 | }; 53 | kernel = new ChimeeKernelHls(videoElement, config, {}); 54 | }); 55 | afterEach(() => { 56 | kernel.destroy(); 57 | videoElement = null; 58 | config = undefined; 59 | }); 60 | it('refresh', async () => { 61 | expect(kernel.config.src).to.equal(config.src); 62 | const videoSrc = kernel.video.src; 63 | await kernel.refresh(); 64 | expect(kernel.config.src).to.equal(config.src); 65 | expect(kernel.video.src).to.equal(videoSrc); 66 | }); 67 | it('load', () => { 68 | expect(kernel.config.src).to.equal(config.src); 69 | const videoSrc = kernel.video.src; 70 | kernel.load(); 71 | expect(kernel.config.src).to.equal(config.src); 72 | expect(kernel.video.src).to.equal(videoSrc); 73 | }); 74 | it('seek', () => { 75 | expect(kernel.video.currentTime).to.equal(0); 76 | kernel.load(); 77 | expect(kernel.video.currentTime).to.equal(0); 78 | kernel.seek(10); 79 | expect(kernel.video.currentTime).to.equal(10); 80 | }); 81 | it('play & pause', () => { 82 | expect(() => { 83 | kernel.attachMedia(); 84 | kernel.load(); 85 | kernel.play(); 86 | kernel.pause(); 87 | }).not.to.throw(); 88 | }); 89 | it('startload & stopLoad', () => { 90 | expect(() => { 91 | kernel.attachMedia(); 92 | kernel.load(); 93 | kernel.stopLoad(); 94 | kernel.startLoad(); 95 | }).not.to.throw(); 96 | }); 97 | }); 98 | 99 | describe('error branch', () => { 100 | let videoElement; 101 | beforeEach(() => { 102 | videoElement = document.createElement('video'); 103 | }); 104 | afterEach(() => { 105 | videoElement = null; 106 | }); 107 | it('no video element', () => { 108 | expect(() => new ChimeeKernelHls()).to.throw('video element passed in chimee-kernel-hls must be a HTMLVideoElement, but not undefined'); 109 | }); 110 | it('no config', () => { 111 | expect(() => new ChimeeKernelHls(videoElement)).to.throw('config of chimee-kernel-hls must be an Object but not undefined'); 112 | }); 113 | it('error handler', done => { 114 | const config = { 115 | src: 'http://cdn.toxicjohann.com', 116 | box: 'hls', 117 | isLive: false, 118 | }; 119 | const kernel = new ChimeeKernelHls(videoElement, config, { 120 | debug: true, 121 | }); 122 | kernel.on('error', () => { 123 | done(); 124 | }); 125 | expect(() => kernel.hlsKernel.trigger('hlsError', { type: 'test', details: 'something wrong', fatal: false })).not.to.throw(); 126 | }); 127 | }); 128 | --------------------------------------------------------------------------------