Compare commits
105 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08b1dd0ba0 | ||
|
|
5c2a3a1fa5 | ||
|
|
67cc21b1fa | ||
|
|
c1a9c715a4 | ||
|
|
ce2e4eb836 | ||
|
|
9e81f203cb | ||
|
|
4a88f47af5 | ||
|
|
3f44579508 | ||
|
|
18490b0496 | ||
|
|
f0d1db9044 | ||
|
|
eaacb94c54 | ||
|
|
352138dfef | ||
|
|
3f90be8598 | ||
|
|
05649aa2fd | ||
|
|
f54adc6b94 | ||
|
|
625b080752 | ||
|
|
1920eb583c | ||
|
|
8be8128d6e | ||
|
|
88826db4fd | ||
|
|
6154b9b734 | ||
|
|
3d02d3a79b | ||
|
|
58d0292ef9 | ||
|
|
1f04169aa5 | ||
|
|
c128f1d3f2 | ||
|
|
fdfa0d8f6f | ||
|
|
9d666e0879 | ||
|
|
6f5ecf878c | ||
|
|
486d64ff19 | ||
|
|
9277f04b4b | ||
|
|
f4708c23f0 | ||
|
|
a87ad7d614 | ||
|
|
8709d37738 | ||
|
|
9fad572ec0 | ||
|
|
1ab3e39ba0 | ||
|
|
ec7cc4bc47 | ||
|
|
f53be95e70 | ||
|
|
1e86878d75 | ||
|
|
e7ace32c3c | ||
|
|
60d3e8f617 | ||
|
|
ff2130138a | ||
|
|
8e208789f0 | ||
|
|
7007ce71ed | ||
|
|
06933e47d8 | ||
|
|
85a89b9b3a | ||
|
|
8ea3b71844 | ||
|
|
6292e62858 | ||
|
|
82bd4f2d76 | ||
|
|
44657181a0 | ||
|
|
8f3c60a1a7 | ||
|
|
dc384ed554 | ||
|
|
12344c958f | ||
|
|
c73cc357b9 | ||
|
|
a68a43ef48 | ||
|
|
b8c453bf48 | ||
|
|
3e4662b337 | ||
|
|
a0c41bba87 | ||
|
|
2226ce41c2 | ||
|
|
355f6a7967 | ||
|
|
fa094782c7 | ||
|
|
487899f934 | ||
|
|
318a1e32f4 | ||
|
|
82796c3801 | ||
|
|
cfb70e5325 | ||
|
|
de6fa8d64f | ||
|
|
4de6e111cc | ||
|
|
fa462d696d | ||
|
|
c2e95265ac | ||
|
|
906adcd5c5 | ||
|
|
9dfdc87983 | ||
|
|
939635ed94 | ||
|
|
3ef10bf093 | ||
|
|
78a6e68421 | ||
|
|
2c88c4dbde | ||
|
|
d931bc6e05 | ||
|
|
4e6725ae94 | ||
|
|
92ce3b5ba7 | ||
|
|
af690c689c | ||
|
|
4ac941b128 | ||
|
|
50c325fcce | ||
|
|
adf1b0b3b9 | ||
|
|
a1a79defd1 | ||
|
|
6b6efffe9f | ||
|
|
7bc922f1d5 | ||
|
|
77dfcbe749 | ||
|
|
813252d0c0 | ||
|
|
7d7c09c870 | ||
|
|
3270140555 | ||
|
|
febf34e8e4 | ||
|
|
ee2cc8eca7 | ||
|
|
88e16f187d | ||
|
|
ce1589ecde | ||
|
|
6d6028125c | ||
|
|
d98ff905b0 | ||
|
|
fda9f2adda | ||
|
|
80c01f93ad | ||
|
|
e92f87544e | ||
|
|
53e809685c | ||
|
|
ff79efca02 | ||
|
|
12ab148f47 | ||
|
|
d74438e300 | ||
|
|
42013ec2c1 | ||
|
|
4854c63fb1 | ||
|
|
c1f9b95a08 | ||
|
|
bcd3b7ba52 | ||
|
|
f4c9fbe61a |
@ -10,3 +10,4 @@ node_modules/
|
|||||||
.github
|
.github
|
||||||
.github_build
|
.github_build
|
||||||
.build
|
.build
|
||||||
|
NONPUBLIC/
|
||||||
131
.github/workflows/build_restreamer-ui.yaml
vendored
131
.github/workflows/build_restreamer-ui.yaml
vendored
@ -1,63 +1,88 @@
|
|||||||
name: 'Build restreamer-ui'
|
name: 'Build main restreamer-ui'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
#workflow_dispatch:
|
workflow_dispatch:
|
||||||
#push:
|
|
||||||
# branches-ignore:
|
|
||||||
# - '**'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
build-frontend:
|
||||||
runs-on: [self-hosted]
|
runs-on: ubuntu-latest
|
||||||
steps:
|
outputs:
|
||||||
- name: Checkout
|
version: ${{ steps.latestversion.outputs.version }}
|
||||||
uses: actions/checkout@v2
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: cardinalby/export-env-action@v1
|
- name: Get latest version from package.json
|
||||||
with:
|
id: latestversion
|
||||||
envFile: '.github_build/Build.restreamer-ui.env'
|
run: |
|
||||||
export: 'true'
|
echo "version=$(cat ./package.json | jq '.version' | sed 's/\"//g')" >> "$GITHUB_OUTPUT"
|
||||||
expandWithJobEnv: 'true'
|
|
||||||
expand: 'true'
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up Node.js
|
||||||
uses: docker/setup-qemu-action@master
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
platforms: all
|
node-version: '21'
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Build React App
|
||||||
id: buildx
|
run: |
|
||||||
uses: docker/setup-buildx-action@master
|
yarn install
|
||||||
|
yarn build
|
||||||
|
env:
|
||||||
|
PUBLIC_URL: './'
|
||||||
|
|
||||||
- name: Cache Docker layers
|
- name: Upload React build as artifact
|
||||||
uses: actions/cache@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: /tmp/.buildx-cache
|
name: restreamerui-main-build
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
path: build/
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-
|
|
||||||
|
|
||||||
- name: Login to DockerHub
|
build-docker:
|
||||||
if: github.event_name != 'pull_request'
|
needs: build-frontend
|
||||||
uses: docker/login-action@v1
|
runs-on: [self-hosted]
|
||||||
with:
|
steps:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
- name: Checkout
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build Multi-Arch
|
- name: Download React build artifact
|
||||||
uses: docker/build-push-action@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
name: restreamerui-main-build
|
||||||
context: .
|
path: build
|
||||||
file: ./Dockerfile
|
|
||||||
build-args: |
|
- name: Docker meta
|
||||||
PUBLIC_URL=./
|
id: meta
|
||||||
NODE_IMAGE=${{ env.NODE_IMAGE }}
|
uses: docker/metadata-action@v5
|
||||||
CADDY_IMAGE=${{ env.CADDY_IMAGE }}
|
with:
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
images: |
|
||||||
push: true
|
datarhei/restreamer-ui
|
||||||
tags: |
|
tags: |
|
||||||
datarhei/restreamer-ui:${{ env.RELEASE }}
|
type=raw,value=latest
|
||||||
datarhei/restreamer-ui:latest
|
type=raw,value=${{ needs.build-frontend.outputs.version }}
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@master
|
||||||
|
with:
|
||||||
|
platforms: all
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@master
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and Push Docker Image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile.workflow
|
||||||
|
build-args: |
|
||||||
|
CADDY_IMAGE=caddy:2.7.6-alpine
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|||||||
88
.github/workflows/build_restreamer-ui_dev.yaml
vendored
Normal file
88
.github/workflows/build_restreamer-ui_dev.yaml
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
name: 'Build dev restreamer-ui'
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
schedule:
|
||||||
|
- cron: '37 4 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-frontend:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: dev
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '21'
|
||||||
|
|
||||||
|
- name: Build React App
|
||||||
|
run: |
|
||||||
|
yarn install
|
||||||
|
yarn build
|
||||||
|
env:
|
||||||
|
PUBLIC_URL: './'
|
||||||
|
|
||||||
|
- name: Upload React build as artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: restreamerui-dev-build
|
||||||
|
path: build/
|
||||||
|
|
||||||
|
build-docker:
|
||||||
|
needs: build-frontend
|
||||||
|
runs-on: [self-hosted]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download React build artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: restreamerui-dev-build
|
||||||
|
path: build
|
||||||
|
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
datarhei/restreamer-ui
|
||||||
|
tags: |
|
||||||
|
type=raw,value=dev
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@master
|
||||||
|
with:
|
||||||
|
platforms: all
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@master
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and Push Docker Image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile.workflow
|
||||||
|
build-args: |
|
||||||
|
CADDY_IMAGE=caddy:2.7.6-alpine
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
73
.github/workflows/build_restreamer_dev.yaml
vendored
73
.github/workflows/build_restreamer_dev.yaml
vendored
@ -1,73 +0,0 @@
|
|||||||
name: 'Build datarhei/restreamer-ui:dev'
|
|
||||||
|
|
||||||
on:
|
|
||||||
#workflow_dispatch:
|
|
||||||
#workflow_call:
|
|
||||||
#push:
|
|
||||||
# branches:
|
|
||||||
# - dev
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
docker:
|
|
||||||
runs-on: [self-hosted]
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
branch:
|
|
||||||
- dev
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ matrix.branch }}
|
|
||||||
|
|
||||||
- uses: actions-ecosystem/action-get-latest-tag@v1
|
|
||||||
id: get-latest-tag
|
|
||||||
with:
|
|
||||||
semver_only: true
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
datarhei/restreamer-ui
|
|
||||||
tags: |
|
|
||||||
type=raw,value=dev,enable=${{ matrix.branch == 'dev' }}
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@master
|
|
||||||
with:
|
|
||||||
platforms: all
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
id: buildx
|
|
||||||
uses: docker/setup-buildx-action@master
|
|
||||||
|
|
||||||
- name: Cache Docker layers
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache
|
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-
|
|
||||||
- name: Login to DockerHub
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Build Multi-Arch
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
build-args: |
|
|
||||||
PUBLIC_URL=/ui
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
# RESTREAMER UI
|
|
||||||
RELEASE=1.6.0
|
|
||||||
NODE_IMAGE=node:19.1-alpine3.16
|
|
||||||
CADDY_IMAGE=caddy:2.6.2-alpine
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@
|
|||||||
/build
|
/build
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
NONPUBLIC
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.VSCodeCounter
|
.VSCodeCounter
|
||||||
.env.local
|
.env.local
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
"it",
|
"it",
|
||||||
"ko",
|
"ko",
|
||||||
"pl",
|
"pl",
|
||||||
"pt",
|
"pt-br",
|
||||||
"ru",
|
"ru",
|
||||||
"sl",
|
"sl",
|
||||||
"tr",
|
"tr",
|
||||||
|
|||||||
48
CHANGELOG.md
48
CHANGELOG.md
@ -1,5 +1,53 @@
|
|||||||
# Restreamer-UI
|
# Restreamer-UI
|
||||||
|
|
||||||
|
## v1.13.0 > v1.14.0
|
||||||
|
|
||||||
|
- Add wettercom service
|
||||||
|
- Add option to select which channels will be displayed on the playersite ([#392](https://github.com/datarhei/restreamer/issues/392), [#800](https://github.com/datarhei/restreamer/issues/800))
|
||||||
|
- Mod updates public videojs >v8
|
||||||
|
- Fix erroneous filter setting
|
||||||
|
- Fix encoded address
|
||||||
|
- Fix double -filter parameter when encoder sets filter
|
||||||
|
- Fix Docker build ([#64](https://github.com/datarhei/restreamer-ui/issues/64))
|
||||||
|
|
||||||
|
## v1.12.0 > v1.13.0
|
||||||
|
|
||||||
|
- Add to allow stream hints in case probing fails
|
||||||
|
- Mod enables ff-loglevel and prepares the logging component
|
||||||
|
- Mod uses official Instagram-RTMP target
|
||||||
|
- Mod Remove unused imports
|
||||||
|
- Mod Update translations
|
||||||
|
- Mod updates dep.
|
||||||
|
- Fix player position
|
||||||
|
- Fix missing stream URL, summarize streams in probe log, don't lock type for first stream
|
||||||
|
|
||||||
|
## v1.11.0 > v1.12.0
|
||||||
|
|
||||||
|
- Add option to select different SRT stream in wizard
|
||||||
|
- Add option to select different RTMP stream in wizard
|
||||||
|
- Fix selecting other than first audio stream ([#710](https://github.com/datarhei/restreamer/issues/710))
|
||||||
|
- Fix reset of previous audio settings when editing profile ([#730](https://github.com/datarhei/restreamer/issues/730))
|
||||||
|
- Fix RTMP URL for receive mode
|
||||||
|
|
||||||
|
## v1.10.0 > v1.11.0
|
||||||
|
|
||||||
|
- Add allow to stream HEVC and AV1 to Youtube via RTMP
|
||||||
|
- Add librav1e AV1 encoder
|
||||||
|
- Add support for AV1 CUDA decoding ([PR 46](https://github.com/datarhei/restreamer-ui/pull/46))
|
||||||
|
- Add FFmpeg 6 support
|
||||||
|
- Add HEVC VideoToolbox encoder
|
||||||
|
- Fix anonymize error message ([#688](https://github.com/datarhei/restreamer/issues/688))
|
||||||
|
- Fix chromecast config ([#37](https://github.com/datarhei/restreamer-ui/issues/37))
|
||||||
|
|
||||||
|
## v1.9.0 > v1.10.0
|
||||||
|
|
||||||
|
- Add resource usage and ffmpeg command to process details
|
||||||
|
- Add audio loop source
|
||||||
|
- Add to allow to select from already publishing RTMP and SRT streams
|
||||||
|
- Fix wrongly displayed SRT URL ([#635](https://github.com/datarhei/restreamer/issues/635))
|
||||||
|
- Fix RTMPS address with custom ports ([#658](https://github.com/datarhei/restreamer/issues/658))
|
||||||
|
- Fix allow RTSPS protocol ([#677](https://github.com/datarhei/restreamer/issues/677))
|
||||||
|
|
||||||
## v1.8.0 > v1.9.0
|
## v1.8.0 > v1.9.0
|
||||||
|
|
||||||
- Add enlarged channel overview
|
- Add enlarged channel overview
|
||||||
|
|||||||
17
Dockerfile
17
Dockerfile
@ -1,22 +1,17 @@
|
|||||||
ARG NODE_IMAGE=node:21-alpine3.17
|
ARG NODE_IMAGE=node:21-alpine3.20
|
||||||
ARG CADDY_IMAGE=caddy:2.7.5-alpine
|
ARG CADDY_IMAGE=caddy:2.8.4-alpine
|
||||||
|
|
||||||
FROM $NODE_IMAGE as builder
|
FROM $NODE_IMAGE AS builder
|
||||||
|
|
||||||
ARG NODE_SPACE_SIZE=10240
|
ENV PUBLIC_URL="./"
|
||||||
ENV NODE_OPTIONS="--openssl-legacy-provider --max-old-space-size=$NODE_SPACE_SIZE"
|
|
||||||
|
|
||||||
ENV PUBLIC_URL "./"
|
|
||||||
|
|
||||||
COPY . /ui
|
COPY . /ui
|
||||||
|
|
||||||
WORKDIR /ui
|
WORKDIR /ui
|
||||||
|
|
||||||
RUN cd /ui && \
|
RUN cd /ui && \
|
||||||
yarn set version berry && \
|
yarn install && \
|
||||||
yarn config set httpTimeout 600000 && \
|
yarn build
|
||||||
yarn install && \
|
|
||||||
yarn run build
|
|
||||||
|
|
||||||
FROM $CADDY_IMAGE
|
FROM $CADDY_IMAGE
|
||||||
|
|
||||||
|
|||||||
13
Dockerfile.workflow
Normal file
13
Dockerfile.workflow
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
ARG CADDY_IMAGE=caddy:2.7.5-alpine
|
||||||
|
FROM $CADDY_IMAGE
|
||||||
|
|
||||||
|
COPY build /ui/build
|
||||||
|
COPY Caddyfile /ui/Caddyfile
|
||||||
|
|
||||||
|
ENV PUBLIC_URL="./"
|
||||||
|
|
||||||
|
WORKDIR /ui
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD [ "caddy", "run", "--config", "/ui/Caddyfile" ]
|
||||||
86
package.json
86
package.json
@ -1,53 +1,52 @@
|
|||||||
{
|
{
|
||||||
"name": "restreamer-ui",
|
"name": "restreamer-ui",
|
||||||
"version": "1.9.0",
|
"version": "1.14.0",
|
||||||
"bundle": "restreamer-v2.7.0",
|
"bundle": "restreamer-v2.12.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth0/auth0-spa-js": "^2.1.2",
|
"@auth0/auth0-spa-js": "^2.1.3",
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-syntax-flow": "^7.24.7",
|
||||||
"@babel/plugin-syntax-flow": "^7.22.5",
|
"@babel/plugin-transform-react-jsx": "^7.25.2",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.22.15",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/styled": "^11.13.0",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@fontsource/dosis": "^5.0.21",
|
||||||
"@fontsource/dosis": "^5.0.15",
|
"@fontsource/roboto": "^5.0.14",
|
||||||
"@fontsource/roboto": "^5.0.8",
|
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
"@fortawesome/free-brands-svg-icons": "^6.6.0",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.4.2",
|
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@lingui/core": "^4.11.4",
|
||||||
"@lingui/core": "^4.5.0",
|
"@lingui/macro": "^4.11.4",
|
||||||
"@lingui/macro": "^4.5.0",
|
"@lingui/react": "^4.11.4",
|
||||||
"@lingui/react": "^4.5.0",
|
"@mui/icons-material": "^6.0.1",
|
||||||
"@mui/icons-material": "^5.14.13",
|
"@mui/lab": "^6.0.0-beta.8",
|
||||||
"@mui/lab": "^5.0.0-alpha.148",
|
"@mui/material": "^6.0.1",
|
||||||
"@mui/material": "^5.14.13",
|
"@mui/styles": "^6.0.1",
|
||||||
"@mui/styles": "^5.14.13",
|
"@testing-library/dom": "^10.4.0",
|
||||||
"@testing-library/dom": "^9.3.3",
|
"@testing-library/jest-dom": "^6.5.0",
|
||||||
"@testing-library/jest-dom": "^6.1.4",
|
"@testing-library/react": "^16.0.1",
|
||||||
"@testing-library/react": "^14.0.0",
|
"@testing-library/user-event": "^14.5.2",
|
||||||
"@testing-library/user-event": "^14.5.1",
|
"@types/react": "^18.3.5",
|
||||||
"@types/react": "^18.2.28",
|
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
"eslint": "^8.51.0",
|
"eslint": "^9.9.1",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"make-plural": "^7.3.0",
|
"make-plural": "^7.4.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.3.1",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-device-detect": "^2.2.3",
|
"react-device-detect": "^2.2.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.3.1",
|
||||||
"react-markdown": "^9.0.0",
|
"react-markdown": "^9.0.1",
|
||||||
"react-router-dom": "^6.16.0",
|
"react-router-dom": "^6.26.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.6.3",
|
||||||
"serve": "^14.2.1",
|
"serve": "^14.2.3",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.5.4",
|
||||||
"url-parse": "^1.5.10",
|
"url-parse": "^1.5.10",
|
||||||
"util": "^0.12.5",
|
"util": "^0.12.5",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^10.0.0",
|
||||||
"video.js": "8.6.1",
|
"video.js": "^8.17.3",
|
||||||
"videojs-overlay": "^3.1.0"
|
"videojs-overlay": "^3.1.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -87,12 +86,13 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.23.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@lingui/cli": "^4.5.0",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"@lingui/cli": "^4.11.4",
|
||||||
|
"babel-core": "^6.26.3",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.3.3",
|
||||||
"react-error-overlay": "^6.0.11"
|
"react-error-overlay": "^6.0.11"
|
||||||
},
|
},
|
||||||
"resolutions": {}
|
"resolutions": {}
|
||||||
}
|
}
|
||||||
778
public/_player/videojs/dist/video-js.css
vendored
778
public/_player/videojs/dist/video-js.css
vendored
File diff suppressed because one or more lines are too long
2
public/_player/videojs/dist/video-js.min.css
vendored
2
public/_player/videojs/dist/video-js.min.css
vendored
File diff suppressed because one or more lines are too long
46801
public/_player/videojs/dist/video.js
vendored
46801
public/_player/videojs/dist/video.js
vendored
File diff suppressed because one or more lines are too long
56
public/_player/videojs/dist/video.min.js
vendored
56
public/_player/videojs/dist/video.min.js
vendored
File diff suppressed because one or more lines are too long
1
public/_player/videojs/dist/videojs-airplay.css
vendored
Normal file
1
public/_player/videojs/dist/videojs-airplay.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.vjs-airplay-button .vjs-icon-placeholder{background:url("ic_airplay_white_24px.svg") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-airplay-button:hover{cursor:pointer}.vjs-airplay-button:hover .vjs-icon-placeholder{background-image:url("ic_airplay_white_24px.svg")}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-airplay-button-label{flex-grow:1;margin-left:4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}
|
||||||
308
public/_player/videojs/dist/videojs-airplay.js
vendored
Normal file
308
public/_player/videojs/dist/videojs-airplay.js
vendored
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var hasAirPlayAPISupport = require('../lib/hasAirPlayAPISupport');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the AirPlayButton Component with Video.js. Calls
|
||||||
|
* {@link http://docs.videojs.com/Component.html#.registerComponent}, which will add a
|
||||||
|
* component called `airPlayButton` to the list of globally registered Video.js
|
||||||
|
* components. The `airPlayButton` is added to the player's control bar UI automatically
|
||||||
|
* once {@link module:enableAirPlay} has been called. If you would like to specify the
|
||||||
|
* order of the buttons that appear in the control bar, including this button, you can do
|
||||||
|
* so in the options that you pass to the `videojs` function when creating a player:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* videojs('playerID', {
|
||||||
|
* controlBar: {
|
||||||
|
* children: [
|
||||||
|
* 'playToggle',
|
||||||
|
* 'progressControl',
|
||||||
|
* 'volumePanel',
|
||||||
|
* 'fullscreenToggle',
|
||||||
|
* 'airPlayButton',
|
||||||
|
* ],
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param videojs {object} A reference to {@link http://docs.videojs.com/module-videojs.html|Video.js}
|
||||||
|
* @see http://docs.videojs.com/module-videojs.html#~registerPlugin
|
||||||
|
*/
|
||||||
|
module.exports = function (videojs) {
|
||||||
|
/**
|
||||||
|
* The AirPlayButton module contains both the AirPlayButton class definition and the
|
||||||
|
* function used to register the button as a Video.js Component.
|
||||||
|
*
|
||||||
|
* @module AirPlayButton
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ButtonComponent = videojs.getComponent('Button');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Video.js Button class is the base class for UI button components.
|
||||||
|
*
|
||||||
|
* @external Button
|
||||||
|
* @see {@link http://docs.videojs.com/Button.html|Button}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @lends AirPlayButton.prototype */
|
||||||
|
class AirPlayButton extends ButtonComponent {
|
||||||
|
/**
|
||||||
|
* This class is a button component designed to be displayed in the
|
||||||
|
* player UI's control bar. It displays an Apple AirPlay selection
|
||||||
|
* list when clicked.
|
||||||
|
*
|
||||||
|
* @constructs
|
||||||
|
* @extends external:Button
|
||||||
|
*/
|
||||||
|
constructor(player, options) {
|
||||||
|
super(player, options);
|
||||||
|
if (!hasAirPlayAPISupport()) {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
this._reactToAirPlayAvailableEvents();
|
||||||
|
if (options.addAirPlayLabelToButton) {
|
||||||
|
this.el().classList.add('vjs-airplay-button-lg');
|
||||||
|
this._labelEl = document.createElement('span');
|
||||||
|
this._labelEl.classList.add('vjs-airplay-button-label');
|
||||||
|
this._labelEl.textContent = this.localize('AirPlay');
|
||||||
|
this.el().appendChild(this._labelEl);
|
||||||
|
} else {
|
||||||
|
this.controlText('Start AirPlay');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides Button#buildCSSClass to return the classes used on the button element.
|
||||||
|
*
|
||||||
|
* @param {DOMElement} el
|
||||||
|
* @see {@link http://docs.videojs.com/Button.html#buildCSSClass|Button#buildCSSClass}
|
||||||
|
*/
|
||||||
|
buildCSSClass() {
|
||||||
|
return 'vjs-airplay-button ' + super.buildCSSClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides Button#handleClick to handle button click events. AirPlay
|
||||||
|
* functionality is handled outside of this class, which should be limited
|
||||||
|
* to UI related logic. This function simply triggers an event on the player.
|
||||||
|
*
|
||||||
|
* @fires AirPlayButton#airPlayRequested
|
||||||
|
* @param {DOMElement} el
|
||||||
|
* @see {@link http://docs.videojs.com/Button.html#handleClick|Button#handleClick}
|
||||||
|
*/
|
||||||
|
handleClick() {
|
||||||
|
this.player().trigger('airPlayRequested');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the underlying DOMElement used by the player.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {DOMElement} either an <audio> or <video> tag, depending on the type of
|
||||||
|
* player
|
||||||
|
*/
|
||||||
|
_getMediaEl() {
|
||||||
|
var playerEl = this.player().el();
|
||||||
|
return playerEl.querySelector('video, audio');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a listener to the `webkitplaybacktargetavailabilitychanged` event, if it is
|
||||||
|
* supported, that will show or hide this button Component based on the availability
|
||||||
|
* of the AirPlay function.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_reactToAirPlayAvailableEvents() {
|
||||||
|
var mediaEl = this._getMediaEl(),
|
||||||
|
self = this;
|
||||||
|
if (!mediaEl || !hasAirPlayAPISupport()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function onTargetAvailabilityChanged(event) {
|
||||||
|
if (event.availability === 'available') {
|
||||||
|
self.show();
|
||||||
|
} else {
|
||||||
|
self.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mediaEl.addEventListener('webkitplaybacktargetavailabilitychanged', onTargetAvailabilityChanged);
|
||||||
|
this.on('dispose', function () {
|
||||||
|
mediaEl.removeEventListener('webkitplaybacktargetavailabilitychanged', onTargetAvailabilityChanged);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
videojs.registerComponent('airPlayButton', AirPlayButton);
|
||||||
|
};
|
||||||
|
|
||||||
|
},{"../lib/hasAirPlayAPISupport":4}],2:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module enableAirPlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
var hasAirPlayAPISupport = require('./lib/hasAirPlayAPISupport');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param {object} the Video.js Player instance
|
||||||
|
* @returns {AirPlayButton} or `undefined` if it does not exist
|
||||||
|
*/
|
||||||
|
function getExistingAirPlayButton(player) {
|
||||||
|
return player.controlBar.getChild('airPlayButton');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the AirPlayButton Component to the player's ControlBar component, if the
|
||||||
|
* AirPlayButton does not already exist in the ControlBar.
|
||||||
|
* @private
|
||||||
|
* @param player {object} the Video.js Player instance
|
||||||
|
* @param options {object}
|
||||||
|
*/
|
||||||
|
function ensureAirPlayButtonExists(player, options) {
|
||||||
|
var existingAirPlayButton = getExistingAirPlayButton(player),
|
||||||
|
indexOpt;
|
||||||
|
if (options.addButtonToControlBar && !existingAirPlayButton) {
|
||||||
|
// Figure out AirPlay button's index
|
||||||
|
indexOpt = player.controlBar.children().length;
|
||||||
|
if (typeof options.buttonPositionIndex !== 'undefined') {
|
||||||
|
indexOpt = options.buttonPositionIndex >= 0 ? options.buttonPositionIndex : player.controlBar.children().length + options.buttonPositionIndex;
|
||||||
|
}
|
||||||
|
player.controlBar.addChild('airPlayButton', options, indexOpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles requests for AirPlay triggered by the AirPlayButton Component.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param player {object} the Video.js Player instance
|
||||||
|
*/
|
||||||
|
function onAirPlayRequested(player) {
|
||||||
|
var mediaEl = player.el().querySelector('video, audio');
|
||||||
|
if (mediaEl && mediaEl.webkitShowPlaybackTargetPicker) {
|
||||||
|
mediaEl.webkitShowPlaybackTargetPicker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an event listener for the `airPlayRequested` event triggered by the AirPlayButton
|
||||||
|
* Component.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param player {object} the Video.js Player instance
|
||||||
|
*/
|
||||||
|
function listenForAirPlayEvents(player) {
|
||||||
|
// Respond to requests for AirPlay. The AirPlayButton component triggers this event
|
||||||
|
// when the user clicks the AirPlay button.
|
||||||
|
player.on('airPlayRequested', onAirPlayRequested.bind(null, player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the AirPlay plugin.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param player {object} the Video.js player
|
||||||
|
* @param options {object} the plugin options
|
||||||
|
*/
|
||||||
|
function enableAirPlay(player, options) {
|
||||||
|
if (!player.controlBar) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hasAirPlayAPISupport()) {
|
||||||
|
listenForAirPlayEvents(player);
|
||||||
|
ensureAirPlayButtonExists(player, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the AirPlay plugin with Video.js. Calls
|
||||||
|
* {@link http://docs.videojs.com/module-videojs.html#~registerPlugin|videojs#registerPlugin},
|
||||||
|
* which will add a plugin function called `airPlay` to any instance of a Video.js player
|
||||||
|
* that is created after calling this function. Call `player.airPlay(options)`, passing in
|
||||||
|
* configuration options, to enable the AirPlay plugin on your Player instance.
|
||||||
|
*
|
||||||
|
* Currently, the only configuration option is:
|
||||||
|
*
|
||||||
|
* * **buttonText** - the text to display inside of the button component. By default,
|
||||||
|
* this text is hidden and is used for accessibility purposes.
|
||||||
|
*
|
||||||
|
* @param {object} videojs
|
||||||
|
* @see http://docs.videojs.com/module-videojs.html#~registerPlugin
|
||||||
|
*/
|
||||||
|
module.exports = function (videojs) {
|
||||||
|
videojs.registerPlugin('airPlay', function (options) {
|
||||||
|
var pluginOptions = Object.assign({
|
||||||
|
addButtonToControlBar: true
|
||||||
|
}, options || {});
|
||||||
|
|
||||||
|
// `this` is an instance of a Video.js Player.
|
||||||
|
// Wait until the player is "ready" so that the player's control bar component has
|
||||||
|
// been created.
|
||||||
|
this.ready(enableAirPlay.bind(this, this, pluginOptions));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
},{"./lib/hasAirPlayAPISupport":4}],3:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var createAirPlayButton = require('./components/AirPlayButton'),
|
||||||
|
createAirPlayPlugin = require('./enableAirPlay');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module index
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the AirPlay plugin and AirPlayButton Component with Video.js. See
|
||||||
|
* {@link module:AirPlayButton} and {@link module:enableAirPlay} for more details about
|
||||||
|
* how the plugin and button are registered and configured.
|
||||||
|
*
|
||||||
|
* @param {object} videojs
|
||||||
|
* @see module:enableAirPlay
|
||||||
|
* @see module:AirPlayButton
|
||||||
|
*/
|
||||||
|
module.exports = function (videojs) {
|
||||||
|
videojs = videojs || window.videojs;
|
||||||
|
createAirPlayButton(videojs);
|
||||||
|
createAirPlayPlugin(videojs);
|
||||||
|
};
|
||||||
|
|
||||||
|
},{"./components/AirPlayButton":1,"./enableAirPlay":2}],4:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module hasAirPlayAPISupport
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the current browser environment supports AirPlay.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {boolean} true if AirPlay support is available
|
||||||
|
*/
|
||||||
|
module.exports = function () {
|
||||||
|
return !!window.WebKitPlaybackTargetAvailabilityEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
},{}],5:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module is used as an entry point for the build system to bundle this plugin into a
|
||||||
|
* single javascript file that can be loaded by a script tag on a web page. The javascript
|
||||||
|
* file that is built assumes that `videojs` is available globally at `window.videojs`, so
|
||||||
|
* Video.js must be loaded **before** this plugin is loaded.
|
||||||
|
*
|
||||||
|
* Run `npm install` and then `grunt build` to build the plugin's bundled javascript
|
||||||
|
* file, as well as the CSS and image assets into the project's `./dist/` folder.
|
||||||
|
*
|
||||||
|
* @module standalone
|
||||||
|
*/
|
||||||
|
|
||||||
|
require('./index')();
|
||||||
|
|
||||||
|
},{"./index":3}]},{},[5]);
|
||||||
@ -1 +1 @@
|
|||||||
.vjs-airplay-button .vjs-icon-placeholder{background:url("ic_airplay_white_24px.svg") center center no-repeat;background-size:contain;display:inline-block;width:20px;height:20px}.vjs-airplay-button:hover{cursor:pointer}.vjs-airplay-button:hover .vjs-icon-placeholder{background-image:url("ic_airplay_white_24px.svg")}
|
.vjs-airplay-button .vjs-icon-placeholder{background:url("ic_airplay_white_24px.svg") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-airplay-button:hover{cursor:pointer}.vjs-airplay-button:hover .vjs-icon-placeholder{background-image:url("ic_airplay_white_24px.svg")}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-airplay-button-label{flex-grow:1;margin-left:4px}.vjs-airplay-button.vjs-airplay-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}
|
||||||
1317
public/_player/videojs/dist/videojs-airplay.min.js
vendored
1317
public/_player/videojs/dist/videojs-airplay.min.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,65 +1 @@
|
|||||||
/** Silvermine Chromecast **/
|
.vjs-chromecast-button .vjs-icon-placeholder{background:url("ic_cast_white_24dp.png") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-chromecast-button:hover{cursor:pointer}.vjs-chromecast-button:hover .vjs-icon-placeholder{background-image:url("ic_cast_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-chromecast-button-label{flex-grow:1;margin-left:4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}.vjs-tech-chromecast{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden}.vjs-tech-chromecast .vjs-tech-chromecast-poster::after{content:" ";display:block;height:2px;width:100px;background-color:#ccc;position:absolute;left:calc(50% - 50px)}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img{max-height:180px;width:auto;border:2px solid #ccc}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty{width:160px;height:90px}.vjs-tech-chromecast .vjs-tech-chromecast-title-container{position:absolute;bottom:50%;margin-bottom:100px;color:#ccc;text-align:center}.vjs-tech-chromecast .vjs-tech-chromecast-title{font-size:22px}.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty{display:none}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle{font-size:18px;padding-top:.5em}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty{display:none}
|
||||||
.vjs-chromecast-button .vjs-icon-placeholder {
|
|
||||||
background: url('ic_cast_white_24dp.png') center center no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
display: inline-block;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
.vjs-chromecast-button:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.vjs-chromecast-button:hover .vjs-icon-placeholder {
|
|
||||||
background-image: url('ic_cast_white_24dp.png');
|
|
||||||
}
|
|
||||||
.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder {
|
|
||||||
background-image: url('ic_cast_connected_white_24dp.png');
|
|
||||||
}
|
|
||||||
.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder {
|
|
||||||
background-image: url('ic_cast_connected_white_24dp.png');
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-poster::after {
|
|
||||||
content: ' ';
|
|
||||||
display: block;
|
|
||||||
height: 2px;
|
|
||||||
width: 100px;
|
|
||||||
background-color: #cccccc;
|
|
||||||
position: absolute;
|
|
||||||
left: calc(50% - 50px);
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-poster-img {
|
|
||||||
max-height: 180px;
|
|
||||||
width: auto;
|
|
||||||
border: 2px solid #cccccc;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty {
|
|
||||||
width: 160px;
|
|
||||||
height: 90px;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-title-container {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 50%;
|
|
||||||
margin-bottom: 100px;
|
|
||||||
color: #cccccc;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-title {
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-subtitle {
|
|
||||||
font-size: 18px;
|
|
||||||
padding-top: 0.5em;
|
|
||||||
}
|
|
||||||
.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
4100
public/_player/videojs/dist/videojs-chromecast.js
vendored
Normal file
4100
public/_player/videojs/dist/videojs-chromecast.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
|||||||
.vjs-chromecast-button .vjs-icon-placeholder{background:url(ic_cast_white_24dp.png) center center no-repeat;background-size:contain;display:inline-block;width:20px;height:20px}.vjs-chromecast-button:hover{cursor:pointer}.vjs-chromecast-button:hover .vjs-icon-placeholder{background-image:url(ic_cast_white_24dp.png)}.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder{background-image:url(ic_cast_connected_white_24dp.png)}.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder{background-image:url(ic_cast_connected_white_24dp.png)}.vjs-tech-chromecast{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden}.vjs-tech-chromecast .vjs-tech-chromecast-poster::after{content:' ';display:block;height:2px;width:100px;background-color:#ccc;position:absolute;left:calc(50% - 50px)}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img{max-height:180px;width:auto;border:2px solid #ccc}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty{width:160px;height:90px}.vjs-tech-chromecast .vjs-tech-chromecast-title-container{position:absolute;bottom:50%;margin-bottom:100px;color:#ccc;text-align:center}.vjs-tech-chromecast .vjs-tech-chromecast-title{font-size:22px}.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty{display:none}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle{font-size:18px;padding-top:.5em}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty{display:none}
|
.vjs-chromecast-button .vjs-icon-placeholder{background:url("ic_cast_white_24dp.png") center center no-repeat;background-size:contain;display:inline-block;width:12px;height:12px}.vjs-chromecast-button:hover{cursor:pointer}.vjs-chromecast-button:hover .vjs-icon-placeholder{background-image:url("ic_cast_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-casting-state:hover .vjs-icon-placeholder{background-image:url("ic_cast_connected_white_24dp.png")}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden){display:flex;align-items:center;width:auto;padding:0 4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-chromecast-button-label{flex-grow:1;margin-left:4px}.vjs-chromecast-button.vjs-chromecast-button-lg:not(.vjs-hidden) .vjs-icon-placeholder{flex-grow:1}.vjs-tech-chromecast{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden}.vjs-tech-chromecast .vjs-tech-chromecast-poster::after{content:" ";display:block;height:2px;width:100px;background-color:#ccc;position:absolute;left:calc(50% - 50px)}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img{max-height:180px;width:auto;border:2px solid #ccc}.vjs-tech-chromecast .vjs-tech-chromecast-poster-img.vjs-tech-chromecast-poster-img-empty{width:160px;height:90px}.vjs-tech-chromecast .vjs-tech-chromecast-title-container{position:absolute;bottom:50%;margin-bottom:100px;color:#ccc;text-align:center}.vjs-tech-chromecast .vjs-tech-chromecast-title{font-size:22px}.vjs-tech-chromecast .vjs-tech-chromecast-title.vjs-tech-chromecast-title-empty{display:none}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle{font-size:18px;padding-top:.5em}.vjs-tech-chromecast .vjs-tech-chromecast-subtitle.vjs-tech-chromecast-subtitle-empty{display:none}
|
||||||
3149
public/_player/videojs/dist/videojs-chromecast.min.js
vendored
3149
public/_player/videojs/dist/videojs-chromecast.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
795
public/_player/videojs/dist/videojs-license.js
vendored
795
public/_player/videojs/dist/videojs-license.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -82,15 +82,14 @@
|
|||||||
liveui: true,
|
liveui: true,
|
||||||
responsive: true,
|
responsive: true,
|
||||||
fluid: true,
|
fluid: true,
|
||||||
sources: [{ src: playerConfig.source, type: 'application/x-mpegURL' }],
|
sources: [{ src: window.location.origin + '/' + playerConfig.source, type: 'application/x-mpegURL' }],
|
||||||
plugins: {
|
|
||||||
license: playerConfig.license
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (playerConfig.chromecast) {
|
if (playerConfig.chromecast) {
|
||||||
config.techOrder = ["chromecast", "html5"];
|
config.techOrder = ["chromecast", "html5"];
|
||||||
config.plugins.chromecast = {};
|
config.plugins.chromecast = {
|
||||||
|
receiverApplicationId: 'CC1AD845'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playerConfig.airplay) {
|
if (playerConfig.airplay) {
|
||||||
@ -130,6 +129,8 @@
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
player.license(playerConfig.license);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoplay === true) {
|
if (autoplay === true) {
|
||||||
|
|||||||
@ -6,25 +6,32 @@ var config = {
|
|||||||
liveui: true,
|
liveui: true,
|
||||||
responsive: true,
|
responsive: true,
|
||||||
fluid: true,
|
fluid: true,
|
||||||
// Needed to append the url orgin in order for the source to properly pass to the cast device
|
// Needed to append the url origin in order for the source to properly pass to the cast device
|
||||||
sources: [{ src: playerConfig.source, type: 'application/x-mpegURL' }],
|
sources: [{ src: window.location.origin + '/' + playerConfig.source, type: 'application/x-mpegURL' }],
|
||||||
plugins: {
|
plugins: {},
|
||||||
license: playerConfig.license,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (chromecast) {
|
if (chromecast) {
|
||||||
config.techOrder = ['chromecast', 'html5'];
|
config.techOrder = ['chromecast', 'html5'];
|
||||||
config.plugins.chromecast = {};
|
// Provide a default reciever application ID
|
||||||
}
|
config.plugins.chromecast = {
|
||||||
|
receiverApplicationId: 'CC1AD845',
|
||||||
if (airplay) {
|
};
|
||||||
config.plugins.airPlay = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var player = videojs('player', config);
|
var player = videojs('player', config);
|
||||||
|
|
||||||
player.ready(function () {
|
player.ready(function () {
|
||||||
|
if (chromecast) {
|
||||||
|
player.chromecast();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (airplay) {
|
||||||
|
player.airPlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
player.license(playerConfig.license);
|
||||||
|
|
||||||
if (playerConfig.logo.image.length != 0) {
|
if (playerConfig.logo.image.length != 0) {
|
||||||
var overlay = null;
|
var overlay = null;
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="favicon.ico" />
|
<link rel="icon" href="favicon.ico" />
|
||||||
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
|
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#282728" />
|
||||||
<meta name="description" content="Restreamer – Video-Streaming" />
|
<meta name="description" content="Restreamer – Video-Streaming" />
|
||||||
<link rel="apple-touch-icon" href="logo192.png" />
|
<link rel="apple-touch-icon" href="logo192.png" />
|
||||||
<link rel="manifest" href="manifest.json" />
|
<link rel="manifest" href="manifest.json" />
|
||||||
|
|||||||
@ -20,6 +20,6 @@
|
|||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"theme_color": "#000000",
|
"theme_color": "#282728",
|
||||||
"background_color": "#ffffff"
|
"background_color": "#282728"
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/I18n.js
24
src/I18n.js
@ -2,7 +2,6 @@ import React from 'react';
|
|||||||
|
|
||||||
import { I18nProvider } from '@lingui/react';
|
import { I18nProvider } from '@lingui/react';
|
||||||
import { i18n } from '@lingui/core';
|
import { i18n } from '@lingui/core';
|
||||||
import * as plurals from 'make-plural/plurals';
|
|
||||||
|
|
||||||
import { messages as EN } from './locales/en/messages.js';
|
import { messages as EN } from './locales/en/messages.js';
|
||||||
import { messages as DA } from './locales/da/messages.js';
|
import { messages as DA } from './locales/da/messages.js';
|
||||||
@ -13,7 +12,7 @@ import { messages as FR } from './locales/fr/messages.js';
|
|||||||
import { messages as IT } from './locales/it/messages.js';
|
import { messages as IT } from './locales/it/messages.js';
|
||||||
import { messages as KO } from './locales/ko/messages.js';
|
import { messages as KO } from './locales/ko/messages.js';
|
||||||
import { messages as PL } from './locales/pl/messages.js';
|
import { messages as PL } from './locales/pl/messages.js';
|
||||||
import { messages as PT } from './locales/pt/messages.js';
|
import { messages as PT } from './locales/pt-br/messages.js';
|
||||||
import { messages as RU } from './locales/ru/messages.js';
|
import { messages as RU } from './locales/ru/messages.js';
|
||||||
import { messages as SL } from './locales/sl/messages.js';
|
import { messages as SL } from './locales/sl/messages.js';
|
||||||
import { messages as TR } from './locales/tr/messages.js';
|
import { messages as TR } from './locales/tr/messages.js';
|
||||||
@ -21,21 +20,6 @@ import { messages as UK } from './locales/uk/messages.js';
|
|||||||
import { messages as ZH } from './locales/zh-hans/messages.js';
|
import { messages as ZH } from './locales/zh-hans/messages.js';
|
||||||
import * as Storage from './utils/storage';
|
import * as Storage from './utils/storage';
|
||||||
|
|
||||||
i18n.loadLocaleData('en', { plurals: plurals.en });
|
|
||||||
i18n.loadLocaleData('da', { plurals: plurals.da });
|
|
||||||
i18n.loadLocaleData('de', { plurals: plurals.de });
|
|
||||||
i18n.loadLocaleData('el', { plurals: plurals.el });
|
|
||||||
i18n.loadLocaleData('es', { plurals: plurals.es });
|
|
||||||
i18n.loadLocaleData('fr', { plurals: plurals.fr });
|
|
||||||
i18n.loadLocaleData('it', { plurals: plurals.it });
|
|
||||||
i18n.loadLocaleData('ko', { plurals: plurals.ko });
|
|
||||||
i18n.loadLocaleData('pl', { plurals: plurals.pl });
|
|
||||||
i18n.loadLocaleData('pt', { plurals: plurals.pt });
|
|
||||||
i18n.loadLocaleData('ru', { plurals: plurals.ru });
|
|
||||||
i18n.loadLocaleData('sl', { plurals: plurals.sl });
|
|
||||||
i18n.loadLocaleData('tr', { plurals: plurals.tr });
|
|
||||||
i18n.loadLocaleData('uk', { plurals: plurals.tr });
|
|
||||||
i18n.loadLocaleData('zh-hans', { plurals: plurals.zh });
|
|
||||||
i18n.load({
|
i18n.load({
|
||||||
en: EN,
|
en: EN,
|
||||||
da: DA,
|
da: DA,
|
||||||
@ -46,7 +30,7 @@ i18n.load({
|
|||||||
it: IT,
|
it: IT,
|
||||||
ko: KO,
|
ko: KO,
|
||||||
pl: PL,
|
pl: PL,
|
||||||
pt: PT,
|
'pt-br': PT,
|
||||||
ru: RU,
|
ru: RU,
|
||||||
sl: SL,
|
sl: SL,
|
||||||
tr: TR,
|
tr: TR,
|
||||||
@ -55,7 +39,7 @@ i18n.load({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const aliases = {
|
const aliases = {
|
||||||
'pt-br': 'pt',
|
pt: 'pt-br',
|
||||||
'zh-cn': 'zh-hans',
|
'zh-cn': 'zh-hans',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,7 +77,7 @@ const getBrowserLanguage = (defaultLanguage) => {
|
|||||||
return match[0].toLowerCase();
|
return match[0].toLowerCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
i18n.activate(getLanguage('en', ['en', 'da', 'de', 'el', 'es', 'fr', 'it', 'ko', 'pl', 'pt', 'ru', 'sl', 'tr', 'uk', 'zh-hans']));
|
i18n.activate(getLanguage('en', ['en', 'da', 'de', 'el', 'es', 'fr', 'it', 'ko', 'pl', 'pt-br', 'ru', 'sl', 'tr', 'uk', 'zh-hans']));
|
||||||
|
|
||||||
export default function Provider(props) {
|
export default function Provider(props) {
|
||||||
return <I18nProvider i18n={i18n}>{props.children}</I18nProvider>;
|
return <I18nProvider i18n={i18n}>{props.children}</I18nProvider>;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
1
src/locales/pt-br/messages.js
Normal file
1
src/locales/pt-br/messages.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -155,14 +155,14 @@ export default function EncodingSelect(props) {
|
|||||||
encoderList.push(
|
encoderList.push(
|
||||||
<MenuItem value={c.coder} key={c.coder}>
|
<MenuItem value={c.coder} key={c.coder}>
|
||||||
{c.name}
|
{c.name}
|
||||||
</MenuItem>
|
</MenuItem>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
encoderList.push(
|
encoderList.push(
|
||||||
<MenuItem value={c.coder} key={c.coder}>
|
<MenuItem value={c.coder} key={c.coder}>
|
||||||
{c.name}
|
{c.name}
|
||||||
</MenuItem>
|
</MenuItem>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ export default function EncodingSelect(props) {
|
|||||||
decoderList.push(
|
decoderList.push(
|
||||||
<MenuItem value={c.coder} key={c.coder}>
|
<MenuItem value={c.coder} key={c.coder}>
|
||||||
{c.name}
|
{c.name}
|
||||||
</MenuItem>
|
</MenuItem>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,7 +91,7 @@ export default function FilterSelect(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filterSettings.push(
|
filterSettings.push(
|
||||||
<Settings key={c.filter} settings={profile.filter.settings[c.filter].settings} onChange={handleFilterSettingsChange(c.filter)} />
|
<Settings key={c.filter} settings={profile.filter.settings[c.filter].settings} onChange={handleFilterSettingsChange(c.filter)} />,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,16 +15,9 @@ const MenuProps = {
|
|||||||
|
|
||||||
export default function Component(props) {
|
export default function Component(props) {
|
||||||
return (
|
return (
|
||||||
<FormControl variant="outlined" fullWidth>
|
<FormControl variant={props.variant} disabled={props.disabled} fullWidth>
|
||||||
<InputLabel>{props.label}</InputLabel>
|
<InputLabel>{props.label}</InputLabel>
|
||||||
<Select
|
<Select multiple value={props.value} onChange={props.onChange} input={<OutlinedInput />} renderValue={props.renderValue} MenuProps={MenuProps}>
|
||||||
multiple
|
|
||||||
value={props.value}
|
|
||||||
onChange={props.onChange}
|
|
||||||
input={<OutlinedInput />}
|
|
||||||
renderValue={(selected) => selected.join(', ')}
|
|
||||||
MenuProps={MenuProps}
|
|
||||||
>
|
|
||||||
{props.children}
|
{props.children}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -32,7 +25,10 @@ export default function Component(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Component.defaultProps = {
|
Component.defaultProps = {
|
||||||
|
variant: 'outlined',
|
||||||
label: '',
|
label: '',
|
||||||
value: [],
|
value: [],
|
||||||
|
disabled: false,
|
||||||
|
renderValue: (selected) => selected.join(', '),
|
||||||
onChange: function (event) {},
|
onChange: function (event) {},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -28,6 +28,8 @@ function init(props) {
|
|||||||
drop: 0,
|
drop: 0,
|
||||||
dup: 0,
|
dup: 0,
|
||||||
frames: 0,
|
frames: 0,
|
||||||
|
cpu: 0,
|
||||||
|
memory: 0,
|
||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,6 +56,32 @@ export default function Progress(props) {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Divider />
|
<Divider />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h4">
|
||||||
|
<strong>
|
||||||
|
<Number value={progress.cpu} digits={2} minDigits={2} />%
|
||||||
|
</strong>
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" gutterBottom>
|
||||||
|
<Trans>CPU</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Divider />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h4">
|
||||||
|
<strong>
|
||||||
|
<Number value={progress.memory / 1024 / 1024} digits={0} minDigits={0} /> MB
|
||||||
|
</strong>
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" gutterBottom>
|
||||||
|
<Trans>Memory</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Divider />
|
||||||
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="h4">
|
<Typography variant="h4">
|
||||||
<strong>
|
<strong>
|
||||||
|
|||||||
@ -41,7 +41,11 @@ export default function Component(props) {
|
|||||||
isCustom: v === props.customKey ? true : false,
|
isCustom: v === props.customKey ? true : false,
|
||||||
});
|
});
|
||||||
|
|
||||||
props.onChange(event);
|
props.onChange({
|
||||||
|
target: {
|
||||||
|
value: v === props.customKey ? value.custom : value.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCustomChange = (event) => {
|
const handleCustomChange = (event) => {
|
||||||
@ -59,7 +63,7 @@ export default function Component(props) {
|
|||||||
options.push(
|
options.push(
|
||||||
<MenuItem key={o.value} value={o.value} disabled={o.disabled === true}>
|
<MenuItem key={o.value} value={o.value} disabled={o.disabled === true}>
|
||||||
{o.label}
|
{o.label}
|
||||||
</MenuItem>
|
</MenuItem>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: [],
|
local: [],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -1,21 +1,22 @@
|
|||||||
import * as AudioDefault from './audio/Default';
|
import * as AudioDefault from './audio/default';
|
||||||
|
|
||||||
import * as NVDEC from './video/NVDEC';
|
import * as NVDEC from './video/nvdec';
|
||||||
import * as H264MMAL from './video/H264MMAL';
|
import * as H264MMAL from './video/h264_mmal';
|
||||||
import * as H264CUVID from './video/H264CUVID';
|
import * as H264CUVID from './video/h264_cuvid';
|
||||||
import * as HEVCCUVID from './video/HEVCCUVID';
|
import * as HEVCCUVID from './video/hevc_cuvid';
|
||||||
import * as MJPEGCUVID from './video/MJPEGCUVID';
|
import * as MJPEGCUVID from './video/mjpeg_cuvid';
|
||||||
import * as MPEG1CUVID from './video/MPEG1CUVID';
|
import * as MPEG1CUVID from './video/mpeg1_cuvid';
|
||||||
import * as MPEG2CUVID from './video/MPEG2CUVID';
|
import * as MPEG2CUVID from './video/mpeg2_cuvid';
|
||||||
import * as MPEG2MMAL from './video/MPEG2MMAL';
|
import * as MPEG2MMAL from './video/mpeg2_mmal';
|
||||||
import * as MPEG4CUVID from './video/MPEG4CUVID';
|
import * as MPEG4CUVID from './video/mpeg4_cuvid';
|
||||||
import * as MPEG4MMAL from './video/MPEG4MMAL';
|
import * as MPEG4MMAL from './video/mpeg4_mmal';
|
||||||
import * as VC1CUVID from './video/VC1CUVID';
|
import * as VC1CUVID from './video/vc1_cuvid';
|
||||||
import * as VC1MMAL from './video/VC1MMAL';
|
import * as VC1MMAL from './video/vc1_mmal';
|
||||||
import * as VideoDefault from './video/Default';
|
import * as VideoDefault from './video/default';
|
||||||
import * as VideoToolbox from './video/VideoToolbox';
|
import * as VideoToolbox from './video/videotoolbox';
|
||||||
import * as VP8CUVID from './video/VP8CUVID';
|
import * as VP8CUVID from './video/vp8_cuvid';
|
||||||
import * as VP9CUVID from './video/VP9CUVID';
|
import * as VP9CUVID from './video/vp9_cuvid';
|
||||||
|
import * as AV1CUVID from './video/av1_cuvid';
|
||||||
|
|
||||||
class Registry {
|
class Registry {
|
||||||
constructor(type) {
|
constructor(type) {
|
||||||
@ -112,6 +113,7 @@ const videoRegistry = new Registry('video');
|
|||||||
|
|
||||||
videoRegistry.Register(VideoDefault);
|
videoRegistry.Register(VideoDefault);
|
||||||
videoRegistry.Register(VideoToolbox);
|
videoRegistry.Register(VideoToolbox);
|
||||||
|
videoRegistry.Register(AV1CUVID);
|
||||||
videoRegistry.Register(NVDEC);
|
videoRegistry.Register(NVDEC);
|
||||||
videoRegistry.Register(H264MMAL);
|
videoRegistry.Register(H264MMAL);
|
||||||
videoRegistry.Register(H264CUVID);
|
videoRegistry.Register(H264CUVID);
|
||||||
|
|||||||
73
src/misc/coders/Decoders/video/av1_cuvid.js
Normal file
73
src/misc/coders/Decoders/video/av1_cuvid.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Helper from '../../helper';
|
||||||
|
|
||||||
|
function init(initialState) {
|
||||||
|
const state = {
|
||||||
|
...initialState,
|
||||||
|
};
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMapping(settings, stream, skills) {
|
||||||
|
stream = Helper.InitStream(stream);
|
||||||
|
skills = Helper.InitSkills(skills);
|
||||||
|
|
||||||
|
const mapping = {
|
||||||
|
global: [],
|
||||||
|
local: ['-hwaccel', 'cuda', '-c:v', 'av1_cuvid'],
|
||||||
|
filter: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Coder(props) {
|
||||||
|
const settings = init(props.settings);
|
||||||
|
const stream = Helper.InitStream(props.stream);
|
||||||
|
const skills = Helper.InitSkills(props.skills);
|
||||||
|
|
||||||
|
const handleChange = (newSettings) => {
|
||||||
|
let automatic = false;
|
||||||
|
if (!newSettings) {
|
||||||
|
newSettings = settings;
|
||||||
|
automatic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
props.onChange(newSettings, createMapping(newSettings, stream, skills), automatic);
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
handleChange(null);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Coder.defaultProps = {
|
||||||
|
stream: {},
|
||||||
|
settings: {},
|
||||||
|
skills: {},
|
||||||
|
onChange: function (settings, mapping) {},
|
||||||
|
};
|
||||||
|
|
||||||
|
// -hwaccel nvdec
|
||||||
|
|
||||||
|
const coder = 'av1_cuvid';
|
||||||
|
const name = 'AV1 (CUVID)';
|
||||||
|
const codecs = ['av1'];
|
||||||
|
const type = 'video';
|
||||||
|
const hwaccel = true;
|
||||||
|
|
||||||
|
function defaults(stream, skills) {
|
||||||
|
const settings = init({});
|
||||||
|
|
||||||
|
return {
|
||||||
|
settings: settings,
|
||||||
|
mapping: createMapping(settings, stream, skills),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { coder, name, codecs, type, hwaccel, defaults, Coder as component };
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: [],
|
local: [],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'h264_cuvid'],
|
local: ['-c:v', 'h264_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'h264_mmal'],
|
local: ['-c:v', 'h264_mmal'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'hevc_cuvid'],
|
local: ['-c:v', 'hevc_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'mjpeg_cuvid'],
|
local: ['-c:v', 'mjpeg_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'mpeg1_cuvid'],
|
local: ['-c:v', 'mpeg1_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'mpeg2_cuvid'],
|
local: ['-c:v', 'mpeg2_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'mpeg2_mmal'],
|
local: ['-c:v', 'mpeg2_mmal'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'mpeg4_cuvid'],
|
local: ['-c:v', 'mpeg4_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'mpeg4_mmal'],
|
local: ['-c:v', 'mpeg4_mmal'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'],
|
local: ['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'vc1_cuvid'],
|
local: ['-c:v', 'vc1_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'vc1_mmal'],
|
local: ['-c:v', 'vc1_mmal'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-hwaccel', 'videotoolbox'],
|
local: ['-hwaccel', 'videotoolbox'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -53,8 +54,8 @@ Coder.defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const coder = 'videotoolbox';
|
const coder = 'videotoolbox';
|
||||||
const name = 'H264 (VideoToolbox)';
|
const name = 'VideoToolbox';
|
||||||
const codecs = ['h264'];
|
const codecs = ['h264', 'hevc', 'vp9', 'mpeg1', 'mpeg2', 'mpeg4'];
|
||||||
const type = 'video';
|
const type = 'video';
|
||||||
const hwaccel = true;
|
const hwaccel = true;
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'vp8_cuvid'],
|
local: ['-c:v', 'vp8_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -17,6 +17,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: ['-c:v', 'vp9_cuvid'],
|
local: ['-c:v', 'vp9_cuvid'],
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -27,6 +27,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -27,6 +27,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [['-vsync', 'drop']],
|
global: [['-vsync', 'drop']],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -15,6 +15,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -24,6 +24,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [['-vsync', 'drop']],
|
global: [['-vsync', 'drop']],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -11,6 +11,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -7,7 +7,7 @@ import { useLingui } from '@lingui/react';
|
|||||||
import { Trans, t } from '@lingui/macro';
|
import { Trans, t } from '@lingui/macro';
|
||||||
|
|
||||||
import Audio from '../../settings/Audio';
|
import Audio from '../../settings/Audio';
|
||||||
import SelectCustom from '../../../../misc/SelectCustom';
|
import SelectCustom from '../../../SelectCustom';
|
||||||
import Helper from '../../helper';
|
import Helper from '../../helper';
|
||||||
|
|
||||||
function init(initialState) {
|
function init(initialState) {
|
||||||
@ -44,6 +44,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [['-vsync', 'drop']],
|
global: [['-vsync', 'drop']],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -23,6 +23,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -23,6 +23,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [['-vsync', 'drop']],
|
global: [['-vsync', 'drop']],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -23,6 +23,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [['-vsync', 'drop']],
|
global: [['-vsync', 'drop']],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -1,26 +1,28 @@
|
|||||||
import * as AudioCopy from './audio/Copy';
|
import * as AudioCopy from './audio/copy';
|
||||||
import * as AudioNone from './audio/None';
|
import * as AudioNone from './audio/none';
|
||||||
import * as AAC from './audio/AAC';
|
import * as AAC from './audio/aac';
|
||||||
import * as AACAudioToolbox from './audio/AACAudioToolbox';
|
import * as AACAudioToolbox from './audio/aac_audiotoolbox';
|
||||||
import * as Libopus from './audio/Libopus';
|
import * as Libopus from './audio/opus_libopus';
|
||||||
import * as Libvorbis from './audio/Libvorbis';
|
import * as Libvorbis from './audio/vorbis_libvorbis';
|
||||||
import * as MP3 from './audio/MP3';
|
import * as MP3 from './audio/mp3_libmp3lame';
|
||||||
import * as Opus from './audio/Opus';
|
import * as Opus from './audio/opus';
|
||||||
import * as Vorbis from './audio/Vorbis';
|
import * as Vorbis from './audio/vorbis';
|
||||||
|
|
||||||
import * as X264 from './video/X264';
|
import * as X264 from './video/h264_libx264';
|
||||||
import * as X265 from './video/X265';
|
import * as X265 from './video/hevc_libx265';
|
||||||
import * as H264VideoToolbox from './video/H264VideoToolbox';
|
import * as H264VideoToolbox from './video/h264_videotoolbox';
|
||||||
import * as H264NVENC from './video/H264NVENC';
|
import * as H264NVENC from './video/h264_nvenc';
|
||||||
import * as H264OMX from './video/H264OMX';
|
import * as H264OMX from './video/h264_omx';
|
||||||
import * as H264V4L2M2M from './video/H264V4L2M2M';
|
import * as H264V4L2M2M from './video/h264_v4l2m2m';
|
||||||
import * as H264VAAPI from './video/H264VAAPI';
|
import * as H264VAAPI from './video/h264_vaapi';
|
||||||
import * as HEVCVAAPI from './video/HEVCVAAPI';
|
import * as HEVCVAAPI from './video/hevc_vaapi';
|
||||||
import * as VP9VAAPI from './video/VP9VAAPI';
|
import * as HEVCVideoToolbox from './video/hevc_videotoolbox';
|
||||||
import * as VideoCopy from './video/Copy';
|
import * as VP9VAAPI from './video/vp9_vaapi';
|
||||||
import * as VideoNone from './video/None';
|
import * as VideoCopy from './video/copy';
|
||||||
import * as VideoRaw from './video/Raw';
|
import * as VideoNone from './video/none';
|
||||||
import * as VP9 from './video/VP9';
|
import * as VideoRaw from './video/rawvideo';
|
||||||
|
import * as VP9 from './video/vp9_libvpx';
|
||||||
|
import * as AV1Rav1e from './video/av1_librav1e';
|
||||||
|
|
||||||
class Registry {
|
class Registry {
|
||||||
constructor(type) {
|
constructor(type) {
|
||||||
@ -123,15 +125,17 @@ const videoRegistry = new Registry('video');
|
|||||||
videoRegistry.Register(VideoCopy);
|
videoRegistry.Register(VideoCopy);
|
||||||
videoRegistry.Register(VideoNone);
|
videoRegistry.Register(VideoNone);
|
||||||
videoRegistry.Register(X264);
|
videoRegistry.Register(X264);
|
||||||
videoRegistry.Register(X265);
|
|
||||||
videoRegistry.Register(H264VideoToolbox);
|
videoRegistry.Register(H264VideoToolbox);
|
||||||
videoRegistry.Register(H264NVENC);
|
videoRegistry.Register(H264NVENC);
|
||||||
videoRegistry.Register(H264OMX);
|
videoRegistry.Register(H264OMX);
|
||||||
videoRegistry.Register(H264V4L2M2M);
|
videoRegistry.Register(H264V4L2M2M);
|
||||||
videoRegistry.Register(H264VAAPI);
|
videoRegistry.Register(H264VAAPI);
|
||||||
|
videoRegistry.Register(X265);
|
||||||
videoRegistry.Register(HEVCVAAPI);
|
videoRegistry.Register(HEVCVAAPI);
|
||||||
|
videoRegistry.Register(HEVCVideoToolbox);
|
||||||
videoRegistry.Register(VP9VAAPI);
|
videoRegistry.Register(VP9VAAPI);
|
||||||
videoRegistry.Register(VP9);
|
videoRegistry.Register(VP9);
|
||||||
|
videoRegistry.Register(AV1Rav1e);
|
||||||
videoRegistry.Register(VideoRaw);
|
videoRegistry.Register(VideoRaw);
|
||||||
|
|
||||||
export { audioRegistry as Audio, videoRegistry as Video };
|
export { audioRegistry as Audio, videoRegistry as Video };
|
||||||
|
|||||||
256
src/misc/coders/Encoders/video/av1_librav1e.js
Normal file
256
src/misc/coders/Encoders/video/av1_librav1e.js
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Grid from '@mui/material/Grid';
|
||||||
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
import TextField from '@mui/material/TextField';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
|
import { Trans } from '@lingui/macro';
|
||||||
|
|
||||||
|
import Select from '../../../Select';
|
||||||
|
import Video from '../../settings/Video';
|
||||||
|
import Helper from '../../helper';
|
||||||
|
|
||||||
|
function init(initialState) {
|
||||||
|
const state = {
|
||||||
|
bitrate: '4096',
|
||||||
|
fps: '25',
|
||||||
|
fps_mode: 'auto',
|
||||||
|
gop: '2',
|
||||||
|
qp: '-1',
|
||||||
|
speed: '-1',
|
||||||
|
tiles: '0',
|
||||||
|
tile_rows: '0',
|
||||||
|
tile_columns: '0',
|
||||||
|
params: '',
|
||||||
|
...initialState,
|
||||||
|
};
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMapping(settings, stream, skills) {
|
||||||
|
stream = Helper.InitStream(stream);
|
||||||
|
skills = Helper.InitSkills(skills);
|
||||||
|
|
||||||
|
const local = [
|
||||||
|
'-codec:v',
|
||||||
|
'librav1e',
|
||||||
|
'-b:v',
|
||||||
|
`${settings.bitrate}k`,
|
||||||
|
'-maxrate:v',
|
||||||
|
`${settings.bitrate}k`,
|
||||||
|
'-bufsize:v',
|
||||||
|
`${settings.bitrate}k`,
|
||||||
|
'-r',
|
||||||
|
`${settings.fps}`,
|
||||||
|
'-pix_fmt',
|
||||||
|
'yuv420p',
|
||||||
|
'-qp',
|
||||||
|
`${settings.qp}`,
|
||||||
|
'-speed',
|
||||||
|
`${settings.speed}`,
|
||||||
|
'-tiles',
|
||||||
|
`${settings.tiles}`,
|
||||||
|
'-tile-rows',
|
||||||
|
`${settings.tile_rows}`,
|
||||||
|
'-tile-columns',
|
||||||
|
`${settings.tile_columns}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (settings.params.length !== 0) {
|
||||||
|
local.push('-rav1e-params', `${settings.params}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.gop !== 'auto') {
|
||||||
|
local.push(
|
||||||
|
'-g',
|
||||||
|
`${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`,
|
||||||
|
'-keyint_min',
|
||||||
|
`${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skills.ffmpeg.version_major >= 5) {
|
||||||
|
local.push('-fps_mode', `${settings.fps_mode}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapping = {
|
||||||
|
global: [],
|
||||||
|
local: local,
|
||||||
|
filter: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Speed(props) {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Select label={<Trans>Speed Preset</Trans>} value={props.value} onChange={props.onChange}>
|
||||||
|
<MenuItem value="-1">auto (-1)</MenuItem>
|
||||||
|
<MenuItem value="0">slowest (0)</MenuItem>
|
||||||
|
<MenuItem value="1">1</MenuItem>
|
||||||
|
<MenuItem value="2">2</MenuItem>
|
||||||
|
<MenuItem value="3">3</MenuItem>
|
||||||
|
<MenuItem value="4">4</MenuItem>
|
||||||
|
<MenuItem value="5">5</MenuItem>
|
||||||
|
<MenuItem value="6">6</MenuItem>
|
||||||
|
<MenuItem value="7">7</MenuItem>
|
||||||
|
<MenuItem value="8">8</MenuItem>
|
||||||
|
<MenuItem value="9">9</MenuItem>
|
||||||
|
<MenuItem value="10">fastest (10)</MenuItem>
|
||||||
|
</Select>
|
||||||
|
<Typography variant="caption">
|
||||||
|
<Trans>What speed preset to use.</Trans>
|
||||||
|
</Typography>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Speed.defaultProps = {
|
||||||
|
value: '-1',
|
||||||
|
onChange: function (event) {},
|
||||||
|
};
|
||||||
|
|
||||||
|
function Coder(props) {
|
||||||
|
const settings = init(props.settings);
|
||||||
|
const stream = Helper.InitStream(props.stream);
|
||||||
|
const skills = Helper.InitSkills(props.skills);
|
||||||
|
|
||||||
|
const handleChange = (newSettings) => {
|
||||||
|
let automatic = false;
|
||||||
|
if (!newSettings) {
|
||||||
|
newSettings = settings;
|
||||||
|
automatic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
props.onChange(newSettings, createMapping(newSettings, stream, skills), automatic);
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = (what) => (event) => {
|
||||||
|
const newSettings = {
|
||||||
|
...settings,
|
||||||
|
[what]: event.target.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChange(newSettings);
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
handleChange(null);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Video.Bitrate value={settings.bitrate} onChange={update('bitrate')} allowCustom />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Video.Framerate value={settings.fps} onChange={update('fps')} allowCustom />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Video.GOP value={settings.gop} onChange={update('gop')} allowAuto allowCustom />
|
||||||
|
</Grid>
|
||||||
|
{skills.ffmpeg.version_major >= 5 && (
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Video.FpsMode value={settings.fps_mode} onChange={update('fps_mode')} />
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Speed value={settings.speed} onChange={update('speed')} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<TextField
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: -1, max: 255 }}
|
||||||
|
label={<Trans>QP</Trans>}
|
||||||
|
value={settings.qp}
|
||||||
|
onChange={update('qp')}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption">
|
||||||
|
<Trans>Constant Quantizer Mode (-1 to 255).</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: -1 }}
|
||||||
|
label={<Trans>Tiles</Trans>}
|
||||||
|
value={settings.tiles}
|
||||||
|
onChange={update('tiles')}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption">
|
||||||
|
<Trans>Number of tiles encode with.</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: -1 }}
|
||||||
|
label={<Trans>Tile Rows</Trans>}
|
||||||
|
value={settings.tile_rows}
|
||||||
|
onChange={update('tile_rows')}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption">
|
||||||
|
<Trans>Number of tiles rows to encode with.</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: -1 }}
|
||||||
|
label={<Trans>Tile Columns</Trans>}
|
||||||
|
value={settings.tile_columns}
|
||||||
|
onChange={update('tile_columns')}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption">
|
||||||
|
<Trans>Number of tiles columns to encode with.</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<TextField variant="outlined" fullWidth label={<Trans>rav1e Parameters</Trans>} value={settings.params} onChange={update('params')} />
|
||||||
|
<Typography variant="caption">
|
||||||
|
<Trans>Set the rav1e configuration using a :-separated list of key=value parameters.</Trans>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Coder.defaultProps = {
|
||||||
|
stream: {},
|
||||||
|
settings: {},
|
||||||
|
skills: {},
|
||||||
|
onChange: function (settings, mapping) {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const coder = 'librav1e';
|
||||||
|
const name = 'AV1 (librav1e)';
|
||||||
|
const codec = 'av1';
|
||||||
|
const type = 'video';
|
||||||
|
const hwaccel = false;
|
||||||
|
|
||||||
|
function summarize(settings) {
|
||||||
|
return `${name}, ${settings.bitrate} kbit/s, ${settings.fps} FPS, Speed: ${settings.speed}, QP: ${settings.qp}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaults(stream, skills) {
|
||||||
|
const settings = init({});
|
||||||
|
|
||||||
|
return {
|
||||||
|
settings: settings,
|
||||||
|
mapping: createMapping(settings, stream, skills),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { coder, name, codec, type, hwaccel, summarize, defaults, Coder as component };
|
||||||
@ -11,6 +11,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SemverSatisfies from 'semver/functions/satisfies';
|
|
||||||
|
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
@ -29,11 +28,6 @@ function createMapping(settings, stream, skills) {
|
|||||||
stream = Helper.InitStream(stream);
|
stream = Helper.InitStream(stream);
|
||||||
skills = Helper.InitSkills(skills);
|
skills = Helper.InitSkills(skills);
|
||||||
|
|
||||||
let ffversion = 4;
|
|
||||||
if (SemverSatisfies(skills.ffmpeg.version, '^5.0.0')) {
|
|
||||||
ffversion = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
const local = [
|
const local = [
|
||||||
'-codec:v',
|
'-codec:v',
|
||||||
'libx264',
|
'libx264',
|
||||||
@ -58,11 +52,11 @@ function createMapping(settings, stream, skills) {
|
|||||||
'-g',
|
'-g',
|
||||||
`${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`,
|
`${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`,
|
||||||
'-keyint_min',
|
'-keyint_min',
|
||||||
`${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`
|
`${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ffversion === 5) {
|
if (skills.ffmpeg.version_major >= 5) {
|
||||||
local.push('-fps_mode', `${settings.fps_mode}`);
|
local.push('-fps_mode', `${settings.fps_mode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +71,7 @@ function createMapping(settings, stream, skills) {
|
|||||||
const mapping = {
|
const mapping = {
|
||||||
global: [],
|
global: [],
|
||||||
local: local,
|
local: local,
|
||||||
|
filter: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -127,11 +122,6 @@ function Coder(props) {
|
|||||||
const stream = Helper.InitStream(props.stream);
|
const stream = Helper.InitStream(props.stream);
|
||||||
const skills = Helper.InitSkills(props.skills);
|
const skills = Helper.InitSkills(props.skills);
|
||||||
|
|
||||||
let ffversion = 4;
|
|
||||||
if (SemverSatisfies(skills.ffmpeg.version, '^5.0.0')) {
|
|
||||||
ffversion = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleChange = (newSettings) => {
|
const handleChange = (newSettings) => {
|
||||||
let automatic = false;
|
let automatic = false;
|
||||||
if (!newSettings) {
|
if (!newSettings) {
|
||||||
@ -167,7 +157,7 @@ function Coder(props) {
|
|||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<Video.GOP value={settings.gop} onChange={update('gop')} allowAuto allowCustom />
|
<Video.GOP value={settings.gop} onChange={update('gop')} allowAuto allowCustom />
|
||||||
</Grid>
|
</Grid>
|
||||||
{ffversion === 5 && (
|
{skills.ffmpeg.version_major >= 5 && (
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Video.FpsMode value={settings.fps_mode} onChange={update('fps_mode')} />
|
<Video.FpsMode value={settings.fps_mode} onChange={update('fps_mode')} />
|
||||||
</Grid>
|
</Grid>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user