diff --git a/.eslintrc.js b/.eslintrc.js index cd00f879d73..b287f88a0c8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -79,7 +79,12 @@ module.exports = { 'no-unused-vars': 0, 'no-undef': 0, 'no-use-before-define': 'off', - '@typescript-eslint/no-unused-vars': 'warn', + '@typescript-eslint/no-unused-vars': [ + 'warn', + { + args: 'none', + }, + ], '@typescript-eslint/prefer-optional-chain': 2, '@typescript-eslint/consistent-type-assertions': [ 2, diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 2c2692be038..00000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,31 +0,0 @@ -# Contributing to hls.js - -:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: - -#### **Did you find a bug?** - -- **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/video-dev/hls.js/issues). - -- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/video-dev/hls.js/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. - -#### **Did you write a patch that fixes a bug?** - -- First, checkout the repository and install required dependencies - -```sh -git clone https://github.com/video-dev/hls.js.git -# setup dev environement -cd hls.js -npm install -# build dist/hls.js, watch file change for rebuild and launch demo page -npm run dev -# lint -npm run lint -# test -npm run test -``` - -- Use [EditorConfig](http://editorconfig.org/) or at least stay consistent to the file formats defined in the `.editorconfig` file. -- Develop in a topic branch, not master - -Thanks! :heart: :heart: :heart: diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index e5fd7a2b28b..5eb6c2195ba 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -5,13 +5,24 @@ about: Create a report to help us improve ### What version of Hls.js are you using? -### What browser and OS are you using? +### What browser and OS (including versions) are you using? ### Test stream: +### Configuration: + + + +``` +{ + "debug": false, + "backBufferLength": 60 +} +``` + ### Checklist @@ -40,7 +51,7 @@ _What actually happened_ ### Console output ``` -Paste the contents of the browser console here. +Paste the contents of the browser console here (with `debug` enabled in your config). ``` ``` diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 0a3403b27ae..00000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 2 -updates: - - package-ecosystem: npm - directory: '/' - schedule: - interval: daily - commit-message: - # prevent netlify build - prefix: '[skip ci]' - open-pull-requests-limit: 99 - versioning-strategy: increase-if-necessary diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 3cf5f8a4cf2..01e8d75aca1 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,28 +1,13 @@ name: Auto Merge Dependency Updates on: - - pull_request + - pull_request_target jobs: - config: - runs-on: ubuntu-latest - outputs: - hasSecret: ${{ steps.check_secret_access.outputs.result == 'true' }} - steps: - - name: check secret access - id: check_secret_access - run: | - if ! [[ -z "$SECRET" ]]; then - echo "::set-output name=result::true" - fi - env: - SECRET: ${{ secrets.CI_GITHUB_TOKEN }} run: - needs: config - if: needs.config.outputs.hasSecret == 'true' runs-on: ubuntu-latest steps: - - uses: tjenkinson/gh-action-auto-merge-dependency-updates@1ff3f19 + - uses: tjenkinson/gh-action-auto-merge-dependency-updates@791110cb91cf883fb4894ffd080ddbe36607cd31 with: repo-token: ${{ secrets.CI_GITHUB_TOKEN }} - allowed-actors: dependabot[bot] + allowed-actors: renovate[bot] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index feb99e82746..e5c24b5d1d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - name: extract tag id: extract_tag - uses: actions/github-script@v3 + uses: actions/github-script@v4 with: script: | const prefix = 'refs/tags/'; @@ -43,6 +43,21 @@ jobs: with: fetch-depth: 0 + - name: check package-lock.json version + id: extract_tag + uses: actions/github-script@v4 + with: + script: | + const fs = require('fs'); + if ( + JSON.parse(fs.readFileSync('./package-lock.json', { encoding: 'utf8' })) + .lockfileVersion !== 2 + ) { + throw new Error( + 'Expecting package-lock.json version to be 2. Please make sure you are using npm 7.' + ); + } + - name: cache node_modules uses: actions/cache@v2 env: @@ -56,9 +71,9 @@ jobs: ${{ runner.os }}- - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: install run: | @@ -80,8 +95,7 @@ jobs: - name: build run: | - npm run type-check - npm run build + npm run build:ci npm run docs # check that hls.js doesn't error if requiring in node # see https://github.com/video-dev/hls.js/pull/1642 @@ -117,9 +131,9 @@ jobs: ${{ runner.os }}- - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: download build uses: actions/download-artifact@v2 @@ -158,9 +172,9 @@ jobs: ${{ runner.os }}- - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: download build uses: actions/download-artifact@v2 @@ -195,9 +209,9 @@ jobs: - uses: actions/checkout@v2 - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: download build uses: actions/download-artifact@v2 @@ -248,9 +262,9 @@ jobs: ${{ runner.os }}- - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: download build uses: actions/download-artifact@v2 @@ -302,9 +316,9 @@ jobs: ${{ runner.os }}- - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: download build uses: actions/download-artifact@v2 @@ -312,7 +326,7 @@ jobs: name: build - name: start SauceConnect tunnel - uses: saucelabs/sauce-connect-action@5c0cf29 + uses: saucelabs/sauce-connect-action@5c0cf29805c7fe68f2dec68c6384332fb1ba73f9 with: username: ${{ secrets.SAUCE_USERNAME }} accessKey: ${{ secrets.SAUCE_ACCESS_KEY }} @@ -328,6 +342,7 @@ jobs: - name: run functional tests run: | npm run test:func + npm run test:func:light env: CI: true SAUCE_TUNNEL_ID: ${{ github.run_id }}-${{ matrix.config }} @@ -392,9 +407,9 @@ jobs: ${{ runner.os }}- - name: use Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '15' - name: download build uses: actions/download-artifact@v2 @@ -402,7 +417,7 @@ jobs: name: build - name: start SauceConnect tunnel - uses: saucelabs/sauce-connect-action@5c0cf29 + uses: saucelabs/sauce-connect-action@5c0cf29805c7fe68f2dec68c6384332fb1ba73f9 with: username: ${{ secrets.SAUCE_USERNAME }} accessKey: ${{ secrets.SAUCE_ACCESS_KEY }} diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml new file mode 100644 index 00000000000..990a3ba0276 --- /dev/null +++ b/.github/workflows/cancel.yml @@ -0,0 +1,14 @@ +name: Cancel +on: + workflow_run: + workflows: ['automerge', 'build', 'codeql-analysis'] + types: + - requested +jobs: + cancel: + runs-on: ubuntu-latest + steps: + - uses: styfle/cancel-workflow-action@3d86a7cc43670094ac248017207be0295edbc31d + name: Cancel Previous Workflow Runs + with: + workflow_id: ${{ github.event.workflow.id }} diff --git a/.gitignore b/.gitignore index 16c67b408e6..7bee6f1318b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,25 @@ coverage/ .idea/* # Build +/lib +# /dist /dist.zip /netlify /api-docs # eslint .eslintcache + +# Visual Studio 2015/2017 cache/options directory +.vs/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +/web.config +/vwd.webinfo + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 00000000000..31354ec1389 --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/scripts/precommit.sh b/.husky/pre-commit similarity index 53% rename from scripts/precommit.sh rename to .husky/pre-commit index 39c90193b1c..ef2c81422df 100755 --- a/scripts/precommit.sh +++ b/.husky/pre-commit @@ -1,5 +1,6 @@ -#!/bin/bash -set -e +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" +set -e npm run lint:staged npm run type-check diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 46a5d086559..00000000000 --- a/.npmignore +++ /dev/null @@ -1,9 +0,0 @@ -demo -docs/html -misc -test -API.md -bower.json -design.md -hls.js.sublime-project -/streams.js diff --git a/.prettierignore b/.prettierignore index a6678488399..8ff372bfac4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,8 @@ -/dist /api-docs -package-lock.json +/api-extractor/report +/api-extractor/report-* /coverage -libs/ +/demo/libs +/dist +/lib +package-lock.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..7fff6a281b0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing to Hls.js + +Thanks for contributing to hls.js. Your time and input are appreciated. To get the most out of the project, please consider the following. + +## General Guidelines + +### API Reference + +Are you having trouble getting started with hls.js, configuration, or integration? If so, please check the [API reference](https://github.com/video-dev/hls.js/blob/master/docs/API.md) +before submitting an issue here. + +### Code of Conduct + +Please review the project [Code of Conduct](https://github.com/video-dev/hls.js/blob/master/CODE_OF_CONDUCT.md) and adhere to the pledge and standards for behavior when filing issues, submitting changes or interacting with maintainers. + +## Reporting bugs + +First, if you found an issue, **ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/video-dev/hls.js/issues). + +If you're unable to find an open issue addressing the problem, open a new one using the [bug report template](https://github.com/video-dev/hls.js/issues/new?template=bug_report.md). As part of your issue, make sure to include: + +- Test stream/page (if possible) +- hls.js configuration +- Steps to reproduce +- Expected behavior +- Actual behavior + +Please be as detailed as possible, provide everything another contributor would need to reproduce and issue, and understand its impact on playback and the end-user experience. + +If the issue is related to your stream, and you cannot share the stream, please include all the information we would need to reproduce the problem. This includes how to generate a stream if necessary. + +## Feature Requests + +File feature requests using the [Feature request template](https://github.com/video-dev/hls.js/issues/new?assignees=&labels=&template=feature_request.md) filling out all parts. + +Like with bug reports, please be as detailed as possible and try to make sure other contributors have everything they need to understand your request and how it will improve the project. + +## Creating PRs + +Pull requests are welcome and pair well with bug reports and feature requests. Here are some tips to follow before submitting your first PR: + +- Use [EditorConfig](https://editorconfig.org) or at least stay consistent to the file formats defined in the `.editorconfig` file. +- Develop in a topic branch (bugfix/describe-your-fix, feature/describe-your-feature), not master +- The pre-commit hook will cover some tasks, but be sure to run `npm run prettier` before staging your commits. +- Make sure your changes pass all the required build and test tasks using `npm run sanity-check` +- Run functional integration tests locally using `npm run test:func` + +## Contact + +If you aren't already a member, consider joining video-dev on Slack https://video-dev.herokuapp.com/ and chatting with us in the `#hlsjs` channel. diff --git a/LICENSE b/LICENSE index 8f263a03ac6..5123bda03fe 100644 --- a/LICENSE +++ b/LICENSE @@ -12,7 +12,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -src/remux/mp4-generator.js and src/demux/exp-golomb.js implementation in this project +src/remux/mp4-generator.js and src/demux/exp-golomb.ts implementation in this project are derived from the HLS library for video.js (https://github.com/videojs/videojs-contrib-hls) That work is also covered by the Apache 2 License, following copyright: diff --git a/MIGRATING.md b/MIGRATING.md new file mode 100644 index 00000000000..a83126bb275 --- /dev/null +++ b/MIGRATING.md @@ -0,0 +1,78 @@ +# Migrating from hls.js 0.x to 1.x + +This guide provides an overview to migrating an application using hls.js from v0.14.x to v1.0.0. + +## Dependencies + +Promise support is now required. If your app requires support for older browsers that do not include support for Promises, +include your own Promise polyfill. + +## Configuration Changes + +### Back Buffer Eviction + +The new `backBufferLength` setting defaults to 90 seconds, and applies to Live and VOD streams. In version 1.0 and up, +the back buffer on VOD content will be cleared by hls.js rather than leaving it up to the browser by default. + +Set `backBufferLength` to `Infinity` and `liveBackBufferLength` to `90` if you would like 1.0 to handle back buffer +eviction for Live and VOD streams as older versions did. While `liveBackBufferLength` can still be used, it has been +marked deprecated and may be removed in an upcoming minor release. + +### Low Latency Streams + +The new `lowLatencyMode` setting is enabled by default. Set to `false` to disable Low-latency part loading and target +latency playback rate adjustment. + +### Chunked Transfer Support (experimental) + +The new experimental `progressive` setting is disabled by default. Set it to `true` to stream and append audio and +video data as it streams for each segment before segment load completion. Not recommended for production or small segments +with only a single GoP or less. + +## Support for Group-Level Track Switching + +- `hls.audioTracks` and `hls.subtitleTracks` as well as `AUDIO_TRACKS_UPDATED` and `SUBTITLE_TRACKS_UPDATED` events only list tracks in the active level's audio/sub GROUP-ID after `LEVEL_LOADING` (this will go unnoticed for streams with no or only one group per track type) + - The `MANIFEST_PARSED` event still reports all tracks when multiple GROUP-ID values are present. Applications that used that event to get tracks would need to be updated in v1 to switch to the corresponding track update events to select available tracks using the available indexes. + - Track ids are no longer indexes of the complete list of audio or subtitle tracks. They are now indexes within each group. So six tracks in two groups that had ids 0,1,2,3,4,5 will now have ids 0,1,2,0,1,2. This allows for tracks to be changed by index/id within the range of available tracks as they were before. +- Added `groupId` to audio and subtitle track loading and loaded events + +## Playback and Level Changes + +- Setting `hls.currentLevel` no longer pauses the media element while clearing the buffer and loading the new level. This can result in a stall error if playback doesn't start within a quarter of a second. Applications implementing manual quality switching with `hls.currentLevel` that do not want a stall reported should either pause or set `video.playbackRate` to `0` until the level switch is complete. + +## Event Changes + +Event order and content have changed in some places. See **Breaking Changes** below, and please report any issues with breaking changes that impact your integrations + +- `FRAG_LOADED` fires after events handled on progress which can include everything up to appending a fragment if workers are disabled (more details below under **Known Issues**) +- `BUFFER_CODECS` data has changed from `{ tracks: { video?, audio? } }` to simply `{ video?, audio? }` +- `BUFFER_APPENDING` data has changed from `{ type, data, parent, content }` to `{ type, data, frag, chunkMeta }` +- `BUFFER_APPENDED` data has changed +- `FRAG_DECRYPT_ERROR` events are now surfaced as a `FRAG_PARSING_ERROR` along with other fragment transmuxing errors +- Added additional error details to help identify the source of certain network error events: + - `SUBTITLE_LOAD_ERROR` + - `SUBTITLE_TRACK_LOAD_TIMEOUT` + - `UNKNOWN` +- Added additional error detail for streams that cannot start because source buffer(s) could not be created after parsing media codecs + - `BUFFER_INCOMPATIBLE_CODECS_ERROR` will fire instead of `BUFFER_CREATED` with an empty `tracks` list. This media error + is fatal and not recoverable. If you encounter this error make sure you include the correct CODECS string in + your manifest, as this is most likely to occur when attempting to play a fragmented mp4 playlist with unknown codecs. + +### Fragment Stats + +- The `stats` object has changed + - `trequest`, `tfirst`, `tload` have been replaced by `loading: HlsProgressivePerformanceTiming` + - `tparsed` has been replaced by `parsing: HlsProgressivePerformanceTiming` +- On the `Fragment` object: + - `hasElementaryStream` function has been removed + - `setElementaryStream` and `_elementaryStreams` have been renamed (these are only for internal use) + +### LL-HLS Parts in events + +- FRAG\_\_\_\_ events are now fired for LL-HLS part events with a `part` property that include the part details. + +### TypeScript + +v0.x types are not compatible with v1.x. Type definitions are now exported with the build and npm package in +`dist/hls.js.d.ts`. Please use these type definitions if you are having trouble with +[DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) `@types/hls.js` and v1.x. diff --git a/README.md b/README.md index 65ddb53a891..55fc4467daf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![npm](https://img.shields.io/npm/v/hls.js.svg?style=flat)](https://npmjs.org/package/hls.js) -[![npm](https://img.shields.io/npm/v/hls.js/alpha.svg?style=flat)](https://www.npmjs.com/package/hls.js/v/alpha) +[![npm](https://img.shields.io/npm/v/hls.js/canary.svg?style=flat)](https://www.npmjs.com/package/hls.js/v/canary) [![](https://data.jsdelivr.com/v1/package/npm/hls.js/badge?style=rounded)](https://www.jsdelivr.com/package/npm/hls.js) [![Sauce Test Status](https://saucelabs.com/buildstatus/robwalch)](https://app.saucelabs.com/u/robwalch) @@ -9,20 +9,20 @@ Join the discussion via [video-dev.org](https://video-dev.org) in #hlsjs (our Sl # ![hls.js](https://cloud.githubusercontent.com/assets/616833/19739063/e10be95a-9bb9-11e6-8100-2896f8500138.png) -hls.js is a JavaScript library which implements an [HTTP Live Streaming] client. +hls.js is a JavaScript library that implements an [HTTP Live Streaming] client. It relies on [HTML5 video][] and [MediaSource Extensions][] for playback. It works by transmuxing MPEG-2 Transport Stream and AAC/MP3 streams into ISO BMFF (MP4) fragments. -This transmuxing could be performed asynchronously using [Web Worker] if available in the browser. +Transmuxing is performed asynchronously using a [Web Worker] when available in the browser. hls.js also supports HLS + fmp4, as announced during [WWDC2016](https://developer.apple.com/videos/play/wwdc2016/504/) -hls.js does not need any player, it works directly on top of a standard HTML`