From a70f683caf43436e3e07b5c6578ee7cb1d885dc1 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Tue, 7 Jun 2022 16:44:04 +0200 Subject: [PATCH 01/78] Fix unable to parse option value "undefined" - see restreamer#356 restreamer#352 --- src/misc/coders/Encoders/video/H264VAAPI.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/misc/coders/Encoders/video/H264VAAPI.js b/src/misc/coders/Encoders/video/H264VAAPI.js index e40c1cd..4ba01c7 100644 --- a/src/misc/coders/Encoders/video/H264VAAPI.js +++ b/src/misc/coders/Encoders/video/H264VAAPI.js @@ -35,8 +35,6 @@ function createMapping(settings) { `${settings.profile}`, '-quality', `${settings.quality}`, - '-level', - `${settings.level}`, '-b:v', `${settings.bitrate}k`, '-maxrate', From fbe9d91eedad8f78be6f0adcbe31b06aa3ae587d Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Tue, 21 Jun 2022 22:15:13 +0200 Subject: [PATCH 02/78] Add Telegram and Owncast to publication services - datarhei/restreamer#369 --- CHANGELOG.md | 6 + src/views/Publication/Services/Owncast.js | 113 ++++++++++++++++++ src/views/Publication/Services/Telegram.js | 108 +++++++++++++++++ src/views/Publication/Services/index.js | 4 + .../Publication/Services/logos/owncast.svg | 1 + .../Publication/Services/logos/telegram.svg | 1 + 6 files changed, 233 insertions(+) create mode 100644 src/views/Publication/Services/Owncast.js create mode 100644 src/views/Publication/Services/Telegram.js create mode 100644 src/views/Publication/Services/logos/owncast.svg create mode 100644 src/views/Publication/Services/logos/telegram.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 764591e..62f0a64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Restreamer-UI +#### v1.1.0 > v1.3.1 + +- Add Owncast to publication services +- Add Telegram to publication services +- Fix VAAPI encoder + #### v1.0.0 > v1.1.0 - Add compatibility list for encoders diff --git a/src/views/Publication/Services/Owncast.js b/src/views/Publication/Services/Owncast.js new file mode 100644 index 0000000..52cad9a --- /dev/null +++ b/src/views/Publication/Services/Owncast.js @@ -0,0 +1,113 @@ +import React from 'react'; + +import { Trans } from '@lingui/macro'; +import Grid from '@mui/material/Grid'; +import Link from '@mui/material/Link'; +import TextField from '@mui/material/TextField'; + +import Logo from './logos/owncast.svg'; + +const id = 'owncast'; +const name = 'Owncast'; +const version = '1.0'; +const stream_key_link = ''; +const description = ( + + Transmit your Livestream to an Owncast server.{' '} + + Here {' '} + + you can find more details about the settings. + +); +const image_copyright = Please get in touch with the operator of the service and check what happens.; +const author = { + creator: { + name: 'datarhei', + link: 'https://github.com/datarhei', + }, + maintainer: { + name: 'datarhei', + link: 'https://github.com/datarhei', + }, +}; +const category = 'software'; +const requires = { + protocols: ['rtmps'], + formats: ['flv'], + codecs: { + audio: ['aac', 'mp3'], + video: ['h264'], + }, +}; + +function ServiceIcon(props) { + return Telegram Logo; +} + +function init(settings) { + const initSettings = { + protocol: 'rtmp://', + server_url: '', + stream_key: '', + ...settings, + }; + + return initSettings; +} + +function Service(props) { + const settings = init(props.settings); + + const handleChange = (what) => (event) => { + const value = event.target.value; + + settings[what] = value; + + const output = createOutput(settings); + + props.onChange([output], settings); + }; + + const createOutput = (settings) => { + const output = { + address: settings.protocol + settings.server_url + '/' + settings.stream_key, + options: ['-f', 'flv'], + }; + + return output; + }; + + return ( + + + Protocol} + value={settings.protocol} + onChange={handleChange('protocol')} + readOnly + disabled + /> + + + Server URL} value={settings.server_url} onChange={handleChange('server_url')} /> + + + Stream Key} value={settings.stream_key} onChange={handleChange('stream_key')} /> + + + ); +} + +Service.defaultProps = { + settings: {}, + skills: {}, + metadata: {}, + streams: [], + onChange: function (output, settings) {}, +}; + +export { id, name, version, stream_key_link, description, image_copyright, author, category, requires, ServiceIcon as icon, Service as component }; diff --git a/src/views/Publication/Services/Telegram.js b/src/views/Publication/Services/Telegram.js new file mode 100644 index 0000000..6b7e721 --- /dev/null +++ b/src/views/Publication/Services/Telegram.js @@ -0,0 +1,108 @@ +import React from 'react'; + +import { Trans } from '@lingui/macro'; +import Grid from '@mui/material/Grid'; +import TextField from '@mui/material/TextField'; + +import Logo from './logos/telegram.svg'; + +const id = 'telegram'; +const name = 'Telegram'; +const version = '1.0'; +const stream_key_link = ''; +const description = ( + + Transmit a Livestream to a Telegram Channel. + +); +const image_copyright = Please get in touch with the operator of the service and check what happens.; +const author = { + creator: { + name: 'datarhei', + link: 'https://github.com/datarhei', + }, + maintainer: { + name: 'datarhei', + link: 'https://github.com/datarhei', + }, +}; +const category = 'platform'; +const requires = { + protocols: ['rtmps'], + formats: ['flv'], + codecs: { + audio: ['aac', 'mp3'], + video: ['h264'], + }, +}; + +function ServiceIcon(props) { + return Telegram Logo; +} + +function init(settings) { + const initSettings = { + protocol: 'rtmps://', + stream_url: '', + stream_key: '', + ...settings, + }; + + return initSettings; +} + +function Service(props) { + const settings = init(props.settings); + + const handleChange = (what) => (event) => { + const value = event.target.value; + + settings[what] = value; + + const output = createOutput(settings); + + props.onChange([output], settings); + }; + + const createOutput = (settings) => { + const output = { + address: settings.protocol + settings.stream_url + settings.stream_key, + options: ['-f', 'flv'], + }; + + return output; + }; + + return ( + + + Protocol} + value={settings.protocol} + onChange={handleChange('protocol')} + readOnly + disabled + /> + + + Server URL} value={settings.stream_url} onChange={handleChange('stream_url')} /> + + + Stream Key} value={settings.stream_key} onChange={handleChange('stream_key')} /> + + + ); +} + +Service.defaultProps = { + settings: {}, + skills: {}, + metadata: {}, + streams: [], + onChange: function (output, settings) {}, +}; + +export { id, name, version, stream_key_link, description, image_copyright, author, category, requires, ServiceIcon as icon, Service as component }; diff --git a/src/views/Publication/Services/index.js b/src/views/Publication/Services/index.js index 3b3901b..f451e95 100644 --- a/src/views/Publication/Services/index.js +++ b/src/views/Publication/Services/index.js @@ -12,11 +12,13 @@ import * as Image2 from './Image2'; import * as Instagram from './Instagram'; import * as Livespotting from './Livespotting'; import * as MPEGTS from './MPEGTS'; +import * as Owncast from './Owncast'; import * as Red5 from './Red5'; import * as Restream from './Restream'; import * as RTMP from './RTMP'; import * as RTSP from './RTSP'; import * as SRT from './SRT'; +import * as Telegram from './Telegram'; import * as Twitch from './Twitch'; import * as Twitter from './Twitter'; import * as UDP from './UDP'; @@ -62,12 +64,14 @@ registry.Register(Twitch); registry.Register(Instagram); registry.Register(Vimeo); registry.Register(Restream); +registry.Register(Telegram); registry.Register(Livespotting); registry.Register(Brightcove); registry.Register(Akamai); registry.Register(DaCast); registry.Register(CDN77); registry.Register(Core); +registry.Register(Owncast); registry.Register(WOWZA); registry.Register(Red5); registry.Register(Icecast); diff --git a/src/views/Publication/Services/logos/owncast.svg b/src/views/Publication/Services/logos/owncast.svg new file mode 100644 index 0000000..ead8505 --- /dev/null +++ b/src/views/Publication/Services/logos/owncast.svg @@ -0,0 +1 @@ + diff --git a/src/views/Publication/Services/logos/telegram.svg b/src/views/Publication/Services/logos/telegram.svg new file mode 100644 index 0000000..fa06cfe --- /dev/null +++ b/src/views/Publication/Services/logos/telegram.svg @@ -0,0 +1 @@ + From ed3d67f33a940c134e38ec0f33a56aa3f907f9a1 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Tue, 21 Jun 2022 22:42:21 +0200 Subject: [PATCH 03/78] Fix publication service icon styles --- CHANGELOG.md | 9 +- src/views/Main/Egress.js | 5 ++ src/views/Publication/Add.js | 76 ++++++++++++---- src/views/Publication/Edit.js | 87 +++++++++++++------ src/views/Publication/Services/Bitmovin.js | 2 +- src/views/Publication/Services/CDN77.js | 2 +- src/views/Publication/Services/Core.js | 2 +- src/views/Publication/Services/DaCast.js | 2 +- src/views/Publication/Services/Icecast.js | 2 +- .../Publication/Services/Livespotting.js | 2 +- src/views/Publication/Services/Red5.js | 2 +- src/views/Publication/Services/Restream.js | 2 +- src/views/Publication/Services/WOWZA.js | 2 +- 13 files changed, 139 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f0a64..2cfb44d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Restreamer-UI -#### v1.1.0 > v1.3.1 +#### v1.1.0 > v1.3.2 -- Add Owncast to publication services -- Add Telegram to publication services -- Fix VAAPI encoder +- Add Owncast to publication services ([#369](https://github.com/datarhei/restreamer/issues/369)) +- Add Telegram to publication services (thx Martin Held) +- Fix publication service icon styles +- Fix VAAPI encoder #### v1.0.0 > v1.1.0 diff --git a/src/views/Main/Egress.js b/src/views/Main/Egress.js index 9ce3ba2..e479ccf 100644 --- a/src/views/Main/Egress.js +++ b/src/views/Main/Egress.js @@ -29,6 +29,11 @@ const useStyles = makeStyles((theme) => ({ minWidth: 30, marginRight: 6, float: 'left', + '& img': { + maxWidth: 22, + maxHeight: 22, + marginBottom: '0!important', + }, }, '& .egress-right-edit': { float: 'right', diff --git a/src/views/Publication/Add.js b/src/views/Publication/Add.js index aa87d0d..0887aaa 100644 --- a/src/views/Publication/Add.js +++ b/src/views/Publication/Add.js @@ -13,6 +13,7 @@ import CircularProgress from '@mui/material/CircularProgress'; import Divider from '@mui/material/Divider'; import Grid from '@mui/material/Grid'; import Link from '@mui/material/Link'; +import Stack from '@mui/material/Stack'; import Tab from '@mui/material/Tab'; import Tabs from '@mui/material/Tabs'; import TextField from '@mui/material/TextField'; @@ -49,6 +50,9 @@ const useStyles = makeStyles((theme) => ({ maxHeight: 64, marginTop: '-0.065em', }, + serviceName: { + marginTop: '-.2rem', + }, buttonGroup: { marginTop: '0.5em', marginBottom: '-0.5em', @@ -375,12 +379,24 @@ export default function Add(props) { - - - - - {service.name} - v{service.version} + + + + + {service.name} + v{service.version} + + {service.description} @@ -418,12 +434,24 @@ export default function Add(props) { - - - - - {service.name} - v{service.version} + + + + + {service.name} + v{service.version} + + @@ -451,12 +479,24 @@ export default function Add(props) { - - - - - {service.name} - v{service.version} + + + + + {service.name} + v{service.version} + + diff --git a/src/views/Publication/Edit.js b/src/views/Publication/Edit.js index 92adeeb..6970ff0 100644 --- a/src/views/Publication/Edit.js +++ b/src/views/Publication/Edit.js @@ -11,6 +11,7 @@ import CircularProgress from '@mui/material/CircularProgress'; import Divider from '@mui/material/Divider'; import Grid from '@mui/material/Grid'; import Link from '@mui/material/Link'; +import Stack from '@mui/material/Stack'; import Tab from '@mui/material/Tab'; import Tabs from '@mui/material/Tabs'; import TextField from '@mui/material/TextField'; @@ -52,6 +53,9 @@ const useStyles = makeStyles((theme) => ({ maxHeight: 64, marginTop: '-0.065em', }, + serviceName: { + marginTop: '-.2rem', + }, })); export default function Edit(props) { @@ -389,12 +393,24 @@ export default function Edit(props) { - - - - - {$service.name} - v{$service.version} + + + + + {$service.name} + v{$service.version} + + {$service.description} @@ -426,15 +442,27 @@ export default function Edit(props) { - - - - - {$service.name} - v{$service.version} + + + + + {$service.name} + v{$service.version} + + - - {$service.description} + + @@ -446,9 +474,6 @@ export default function Edit(props) { - - - {$unsavedChanges === true && ( @@ -490,15 +515,27 @@ export default function Edit(props) { - - - - - {$service.name} - v{$service.version} + + + + + {$service.name} + v{$service.version} + + - - {$service.description} + + diff --git a/src/views/Publication/Services/Bitmovin.js b/src/views/Publication/Services/Bitmovin.js index 6906cf9..d7f0f5e 100644 --- a/src/views/Publication/Services/Bitmovin.js +++ b/src/views/Publication/Services/Bitmovin.js @@ -42,7 +42,7 @@ const requires = { }; function ServiceIcon(props) { - return Bitmovin Logo; + return Bitmovin Logo; } function init(settings) { diff --git a/src/views/Publication/Services/CDN77.js b/src/views/Publication/Services/CDN77.js index 33ec340..fb341d6 100644 --- a/src/views/Publication/Services/CDN77.js +++ b/src/views/Publication/Services/CDN77.js @@ -42,7 +42,7 @@ const requires = { }; function ServiceIcon(props) { - return DaCast Logo; + return DaCast Logo; } function init(settings) { diff --git a/src/views/Publication/Services/Core.js b/src/views/Publication/Services/Core.js index cd76e70..4ee99b2 100644 --- a/src/views/Publication/Services/Core.js +++ b/src/views/Publication/Services/Core.js @@ -45,7 +45,7 @@ const requires = { }; function ServiceIcon(props) { - return datarhei.com Logo; + return datarhei.com Logo; } function init(settings) { diff --git a/src/views/Publication/Services/DaCast.js b/src/views/Publication/Services/DaCast.js index 150d056..77d8410 100644 --- a/src/views/Publication/Services/DaCast.js +++ b/src/views/Publication/Services/DaCast.js @@ -45,7 +45,7 @@ const requires = { }; function ServiceIcon(props) { - return DaCast Logo; + return DaCast Logo; } function init(settings) { diff --git a/src/views/Publication/Services/Icecast.js b/src/views/Publication/Services/Icecast.js index 727923e..ba3fd2e 100644 --- a/src/views/Publication/Services/Icecast.js +++ b/src/views/Publication/Services/Icecast.js @@ -48,7 +48,7 @@ const requires = { }; function ServiceIcon(props) { - return Icecat Logo; + return Icecat Logo; } function init(settings, metadata) { diff --git a/src/views/Publication/Services/Livespotting.js b/src/views/Publication/Services/Livespotting.js index 6ba2af8..9374fc9 100644 --- a/src/views/Publication/Services/Livespotting.js +++ b/src/views/Publication/Services/Livespotting.js @@ -42,7 +42,7 @@ const requires = { }; function ServiceIcon(props) { - return livespotting.com Logo; + return livespotting.com Logo; } function init(settings) { diff --git a/src/views/Publication/Services/Red5.js b/src/views/Publication/Services/Red5.js index 1e6aa3e..83ce49d 100644 --- a/src/views/Publication/Services/Red5.js +++ b/src/views/Publication/Services/Red5.js @@ -44,7 +44,7 @@ const requires = { }; function ServiceIcon(props) { - return Red5 Logo; + return Red5 Logo; } function init(settings) { diff --git a/src/views/Publication/Services/Restream.js b/src/views/Publication/Services/Restream.js index 88b3569..7d2b009 100644 --- a/src/views/Publication/Services/Restream.js +++ b/src/views/Publication/Services/Restream.js @@ -45,7 +45,7 @@ const requires = { }; function ServiceIcon(props) { - return restream.io Logo; + return restream.io Logo; } function init(settings) { diff --git a/src/views/Publication/Services/WOWZA.js b/src/views/Publication/Services/WOWZA.js index ea67d02..4cc7c43 100644 --- a/src/views/Publication/Services/WOWZA.js +++ b/src/views/Publication/Services/WOWZA.js @@ -47,7 +47,7 @@ const requires = { }; function ServiceIcon(props) { - return wowza.com Logo; + return wowza.com Logo; } function init(settings) { From c8d9b93405e92db56f6957ebd46d8105ac4ad256 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Tue, 21 Jun 2022 23:10:06 +0200 Subject: [PATCH 04/78] Fix process report naming --- CHANGELOG.md | 3 ++- src/views/Publication/Edit.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cfb44d..7c46320 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # Restreamer-UI -#### v1.1.0 > v1.3.2 +#### v1.1.0 > v1.3.3 - Add Owncast to publication services ([#369](https://github.com/datarhei/restreamer/issues/369)) - Add Telegram to publication services (thx Martin Held) +- Fix process debug > process report - Fix publication service icon styles - Fix VAAPI encoder diff --git a/src/views/Publication/Edit.js b/src/views/Publication/Edit.js index 6970ff0..31c4269 100644 --- a/src/views/Publication/Edit.js +++ b/src/views/Publication/Edit.js @@ -493,7 +493,7 @@ export default function Edit(props) { Process details - Process debug + Process report From f8a899ca0f111debd2d201466a7e3e5f8942a87a Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Thu, 23 Jun 2022 22:39:35 +0200 Subject: [PATCH 05/78] =?UTF-8?q?Add=20Polish=20translation=20(thx=20Rober?= =?UTF-8?q?t=20Ryka=C5=82a)=20&=20improvements=20(repo-merge)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update language files - Add Polish translation (thx Robert Rykała) Co-Authored-By: Ingo Oppermann <57445+ioppermann@users.noreply.github.com> --- .linguirc | 1 + CHANGELOG.md | 5 +- package.json | 4 +- src/I18n.js | 11 +- src/locales/de/messages.po | 6 +- src/locales/en/messages.po | 6 +- src/locales/es/messages.po | 6 +- src/locales/fr/messages.po | 6 +- src/locales/it/messages.po | 6 +- src/locales/pl/messages.js | 1 + src/locales/pl/messages.po | 2674 ++++++++++++++++++++++++++++++ src/locales/pt/messages.po | 6 +- src/locales/ru/messages.po | 6 +- src/misc/LanguageSelect.js | 3 +- src/utils/restreamer.js | 6 +- src/views/Edit/ProfileSummary.js | 4 +- 16 files changed, 2716 insertions(+), 35 deletions(-) create mode 100644 src/locales/pl/messages.js create mode 100644 src/locales/pl/messages.po diff --git a/.linguirc b/.linguirc index 69ba787..af356f2 100644 --- a/.linguirc +++ b/.linguirc @@ -17,6 +17,7 @@ "de", "fr", "it", + "pl", "pt", "es", "ru" diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c46320..9d0af8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Restreamer-UI -#### v1.1.0 > v1.3.3 +#### v1.1.0 > v1.4.0 - Add Owncast to publication services ([#369](https://github.com/datarhei/restreamer/issues/369)) - Add Telegram to publication services (thx Martin Held) -- Fix process debug > process report +- Add Polish translations (thx Robert Rykała) +- Fix process report naming - Fix publication service icon styles - Fix VAAPI encoder diff --git a/package.json b/package.json index 3c27df3..a454a81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "restreamer-ui", - "version": "1.1.0", - "bundle": "restreamer-v2.1.0", + "version": "1.4.0", + "bundle": "restreamer-v2.x.x", "private": false, "license": "Apache-2.0", "dependencies": { diff --git a/src/I18n.js b/src/I18n.js index 958e1c9..57d8767 100644 --- a/src/I18n.js +++ b/src/I18n.js @@ -6,27 +6,30 @@ import * as plurals from 'make-plural/plurals'; import { messages as EN } from './locales/en/messages.js'; import { messages as DE } from './locales/de/messages.js'; +import { messages as ES } from './locales/es/messages.js'; import { messages as FR } from './locales/fr/messages.js'; import { messages as IT } from './locales/it/messages.js'; +import { messages as PL } from './locales/pl/messages.js'; import { messages as PT } from './locales/pt/messages.js'; -import { messages as ES } from './locales/es/messages.js'; import { messages as RU } from './locales/ru/messages.js'; import * as Storage from './utils/storage'; i18n.loadLocaleData('en', { plurals: plurals.en }); i18n.loadLocaleData('de', { plurals: plurals.de }); +i18n.loadLocaleData('es', { plurals: plurals.es }); i18n.loadLocaleData('fr', { plurals: plurals.fr }); i18n.loadLocaleData('it', { plurals: plurals.it }); +i18n.loadLocaleData('pl', { plurals: plurals.pl }); i18n.loadLocaleData('pt', { plurals: plurals.pt }); -i18n.loadLocaleData('es', { plurals: plurals.es }); i18n.loadLocaleData('ru', { plurals: plurals.ru }); i18n.load({ en: EN, de: DE, + es: ES, fr: FR, it: IT, + pl: PL, pt: PT, - es: ES, ru: RU, }); @@ -56,7 +59,7 @@ const getBrowserLanguage = (defaultLanguage) => { return match[0].toLowerCase(); }; -i18n.activate(getLanguage('en', ['en', 'de', 'fr', 'it', 'pt', 'es', 'ru'])); +i18n.activate(getLanguage('en', ['en', 'de', 'es', 'fr', 'it', 'pl', 'pt', 'ru'])); export default function Provider(props) { return {props.children}; diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po index 37b0d7e..e86979e 100644 --- a/src/locales/de/messages.po +++ b/src/locales/de/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Verarbeitung & Steuerung" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Daten abholen oder empfangen:" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Qualität" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Raspberry Pi Kamera" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Ratenkontrolle" diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index 1c055d0..35a3c2f 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Processing & Control" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Pull or recieve the data:" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Quality" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Raspberry Pi camera" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Rate control" diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index cbb38b6..25d555d 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Procesamiento y control" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Tire o reciba los datos:" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Calidad" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Cámara Raspberry Pi" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Control de la tasa" diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index 555393c..478d828 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Traitement et contrôle" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Tirer ou recevoir les données :" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Qualité" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Caméra Raspberry Pi" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Contrôle du taux" diff --git a/src/locales/it/messages.po b/src/locales/it/messages.po index 9530ae3..53cbcd6 100644 --- a/src/locales/it/messages.po +++ b/src/locales/it/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Elaborazione e controllo" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Tirare o ricevere i dati:" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Qualità" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Fotocamera Raspberry Pi" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Controllo del tasso" diff --git a/src/locales/pl/messages.js b/src/locales/pl/messages.js new file mode 100644 index 0000000..fe2a984 --- /dev/null +++ b/src/locales/pl/messages.js @@ -0,0 +1 @@ +/*eslint-disable*/module.exports={messages:{"<0>Compatibility list":"<0>Lista kompatybilności","<0>Show probe details":"<0>Pokaż szczegóły sondy","ALSA":"ALSA","API endpoint not found. Settings not saved.":"Nie znaleziono punktu końcowego interfejsu API. Ustawienia nie zostały zapisane.","AVFoundation":"AVFoundation","Abort":"Anuluj","About":"W związku z","Add":"Dodaj","Add Publication":"Dodaj Publikację","Add external widgets and styles to the publication site. You can find some examples on the help page.":"Dodaj widżety i style zewnętrzne do witryny publikowania. Kilka przykładów znajdziesz na stronie pomocy.","Add new channel":"Dodaj nowy kanał","Add: {0}":["Dodaj : ",["0"]],"Address":"Adres","Address for the background image.":"Adres obrazu tła.","Address to listen on for HTTP requests.":"Adres do nasłuchiwania żądań HTTP.","Address to listen on for HTTPS requests.":"Adres do nasłuchiwania żądań HTTPS.","Adjust publication site colors and background as you like.":"Dostosuj kolory i tło witryny publikowania zgodnie z potrzebami.","Advanced monitoring":"Zaawansowane monitorowanie","Advanced settings":"Zaawansowane ustawienia","Advanced setup":"Ustawienia zaawansowane","Alerting by email":"Powiadomienie e-mail","All":"Wszystko","All important system settings.":"Wszystkie ważne parametry systemu.","Allow all referrer":"Zezwól wszystkim odsyłającym","Allow counting how many viewers the stream has.":"Pozwala policzyć liczbę widzów strumienia.","Amplitude":"Zasięg","An environment variable sets this value.":"Zmienna środowiskowa ustawia tę wartość.","App":"App","Application":"Aplikacja","Are you sure you want to abort the wizard?":"Czy na pewno chcesz przerwać kreatorowi?","Audio":"Dźwięk","Audio Device":"Urządzenie Dźwiękowe","Audio device":"Urządzenie audio","Audio from device":"Dźwięk z urządzenia","Audio settings":"Parametry dźwięku","Audio setup":"Ustawienia dźwięku","Auth0":"Auth0","Auth0 Tenant":"Auth0 Najemca","Auth0 is currently not available because this interface is loaded from an insecure origin.":"Auth0 jest obecnie niedostępne, ponieważ ten interfejs jest ładowany z niezabezpieczonego źródła.","Author":"Autor","Authorization":"Uprawnienie","Automatic cleanup of all media data":"Automatyczne czyszczenie wszystkich danych multimedialnych","Autoplay":"Automatyczne odtwarzanie (Autoplay)","Available":"Dostępne na","Back":"Wstecz","Background colors":"Kolory tła","Background image":"Obraz tła","Backup URL":"Link do kopii zapasowej","Backup server":"Serwer kopii zapasowej","Backup stream":"Zapasowy stream","Backup stream key":"Klucz streamu kopii zapasowej","Bandwidth":"Pasmo","Bandwidth control":"Kontrola przepustowości","Banner":"Baner","Basic":"Zasadniczy","Beep factor":"Współczynnik sygnału dźwiękowego","Bitrate":"Bitrate","Briefly describe what the audience will see during the live stream.":"Krótko opisz, co widzowie zobaczą podczas transmisji na żywo.","Button color":"Kolor przycisku","Cache for files on /data.":"Buforowane pliki w /data.","Cache time (Seconds)":"Czas buforowania (w sekundach)","Cache types":"Rodzaje buforu","Capture clicks":"Przechwyt kliknięć","Capture cursor":"Przechwyt kursoru","Channel \"{0}\" saved":["Kanał \"",["0"],"” został zapisany"],"Channels":"Kanały","Check for updates":"Sprawdź aktualizacje","Check the requirements":"Sprawdź wymagania","Choose a video stream":"Wybierz strumień wideo","Choose an audio stream":"Wybierz strumień dźwiękowy","Choose an input device ...":"Wybierz urządzenie wejściowe ...","Choose codec ...":"Wybierz kodek ...","Choose tenant ...":"Wybór najemcy...","Chunk":"Kawałek","Close":"Zamknij","Code injection":"Wstrzyknięcie kodu","Codec":"Kodek","Color":"Kolor","Config":"Config","Confirm password":"Potwierdź hasło","Connect":"Zaloguj się","Connected device":"Urządzenie podłączone ","Connected since <0/>":"Zalogowany od ","Connecting ...":"Zalogowany ...","Connecting to Restreamer Core ...":"Łączenie z Restreamer Core ...","Connecting to Restreamer Core failed probably because of mixed content.":"Połączenie z Restreamer Core nie powiodło się, prawdopodobnie z powodu mieszanej zawartości.","Content":"Zawartość","Content URL":"Content URL","Cores":"Rdzenie","Create user":"Utwórz użytkownika","Creative Commons":"Creative Commons","Custom ...":"Dostosuj ...","Custom JSON config for datarhei Core.":"Własna konfiguracja JSON dla Datarhei Core.","Custom audio device":"Własne urządzenie audio","Custom audio index":"Własny indeks audio","Custom bitrate (kbit/s)":"Własna szybkość transmisji (kb/s)","Custom code injection":"Wstrzyknięcie własnego kodu","Custom delay":"Własny limit czasu","Custom device":"Własne urządzenie","Custom format":"Własny format","Custom framerate":"Własna częstotliwość odświeżania","Custom keyframe interval":"Własny interwał klatki kluczowej","Custom layout":"Własny układ","Custom sampling (Hz)":"Własne próbkowanie (Hz)","Custom scale":"Własna skala","Custom size":"Własny rozmiar","Custom video device":"Własne urządzenie wideo","Custom video index":"Własny indeks wideo","Data copied to clipboard":"Dane skopiowane do schowka","Death color":"Kolor śmierci","Decoder":"Dekoder","Default":"Domyślny","Delay":"Limit czasu","Delay (ms)":"Opóźnienie (w ms)","Delete":"Usuń","Deleting a publication service cannot be reversed. The publication stops immediately.":"Usunięcia usługi publikowania nie można cofnąć. Publikowanie zatrzymuje się natychmiast.","Delivering mode":"Sposób dostawy","Description":"Opis","Design":"Model","Device":"Urządzenie","Disconnect":"Wyloguj","Disconnect & Continue":"Odłącz i kontynuuj","Disconnecting ...":"Wylogowywanie ...","Disk":"Dysk","Disk cache":"Dysk z pamięci podręcznej","Disk storage":"Miejsce na dysku","Do you really want to restart the application now?":"Czy na pewno chcesz teraz ponownie uruchomić aplikację?","Do you want to delete \"{0}\"?":["Czy chcesz usunąć \"",["0"],"”?"],"Do you want to delete {title}?":["Czy chcesz usunąć ",["title"],"?"],"Do you want to disconnect \"{0}\"?":["Czy chcesz odłączyć \"",["0"],"”?"],"Docs":"Dokumenty","Documentation":"Dokumentacja","Dup. frames":"Ramki podwaniające","EDIT: Player":"EDIT: Gracz","EDIT: Publication Website":"EDIT: Witryna publikacji","Edit":"Edytuj","Edit the audio and video sources for the live stream. Add a description, and set your desired content license.":"Zmień źródła audio i wideo dla transmisji na żywo. Dodaj opis i ustaw licencję na żądaną zawartość.","Edit: {title}":["Edytuj: ",["title"]],"Embed":"Integruj","Enable RTMP server ...":"Aktywuj serwer RTMP ...","Enable a periodic beep every second with this value times the carrier frequency":"Aktywuje okresowy sygnał dźwiękowy co sekundę z tą wartością pomnożoną przez częstotliwość nośną","Enable backup stream":"Aktywuj kopie streamu","Enable nerd statistics":"Włącz statystyki nerdów","Enable primary stream":"Aktywuj podstawowy stream","Enable snapshots":"Włącz migawki","Enabling authorization is strongly advised. Otherwise, anybody can access this instance.":"Zdecydowanie zaleca się aktywację autoryzacji. W przeciwnym razie każdy może uzyskać dostęp do tej instancji.","Enabling basic auth is strongly advised. Otherwise, anybody could write data to /memfs.":"Zdecydowanie zaleca się włączenie uwierzytelniania podstawowego. W przeciwnym razie każdy mógłby zapisać dane do /memfs.","Encoder":"Koder","Encoding":"Kodowanie","Encryption":"Szyfrowanie","Enter a name for the new channel.":"Wpisz nazwę nowego kanału.","Enter password":"Wpisz hasło","Enter the address of your network source:":"Wprowadź adres źródła sieci:","Enter username":"Wpisz login","Entropy coder":"Koder entropii","Error":"Błąd","Error while copying data to clipboard":"Błąd podczas kopiowania danych do schowka","Error: {0}":["Błąd: ",["0"]],"Expands the area above the channel list (live chat).":"Rozwija obszar nad listą kanałów (czat na żywo).","Expands the area under the channel description (comment boxes).":"Rozwija obszar pod opisem kanału (pola komentarzy).","Expert mode":"Tryb ekspercki","Extend channel list":"Rozwiń listę kanałów","Extend content":"Rozwiń zawartość","Extend footer":"Rozszerz stopkę","Extend header":"Rozszerz nagłówek","FFmpeg":"FFmpeg","FPS":"FPS","Failed to create publication service ({0})":["Nie udało się utworzyć usługi publikowania (",["0"],")"],"Failed to create publication website files.":"Nie udało się utworzyć publikowanych plików witryny.","Failed to probe the source. Please check the <0>probe details.":"Nie można zbadać źródła. Sprawdź <0>szczegóły sondy.","Failed to refresh token: {0}":["Nie udało się odświeżyć tokena: ",["0"]],"Failed to save ingest metadata":"Nie udało się zapisać metadanych pozyskiwania","Failed to stop process":"Zakończenie procesu nie powiodło się","Failed to store player size setting.":"Nie udało się zapisać ustawienia rozmiaru dysku.","Failed to store publication service ({0})":["Nie udało się zapisać usługi publikowania (",["0"],")"],"Failed to update ingest process ({0})":["Nie udało się zaktualizować procesu przetwarzania (",["0"],")"],"Failed to update the player":"Aktualizacja odtwarzacza nie powiodła się","Failed to verify the source. Please check the address.":"Nie można zweryfikować źródła. Zweryfikuj adres.","Finish":"Wykończenie","Flags":"Flagi","For Javascripts.":"Dla JavaScriptów.","For Stylesheets.":"Do arkuszy stylów.","Force input framerate":"Wymuś częstotliwość odświeżania wejściowego","Format":"Format","Frame drops":"Spadki ramek","Framebuffer":"Framebuffer","Framerate":"Częstotliwość wyświetlania klatek","Frequency (Hz)":"Częstotliwość (Hz)","GET":"GET","General":"Główny","Google Analytics ID":"Google Analytics ID","Google Analytics Tracker Name":"Google Analytics Tracker Name","HLS":"HLS","HLS URL":"Adres URL HLS","HLS statistic for the In-memory storage":"Statystyki HLS dotyczące przechowywania w pamięci","HTTP and HTTPS":"HTTP i HTTPS","HTTP port":"Port HTTP","HTTPS (SSL/TLS)":"HTTPS (SSL/TLS)","HTTPS port":"Port HTTPS","Hardware device":"Urządzenie sprzętowe","Header":"Nagłówek","Headline":"Wyróżniony","Hosted Restreamer interface":"Interfejs hostowany przez Restreamer","Human readable name on the service.":"Nazwa czytelna dla człowieka w usłudze.","IP address":"Adres IP","If you changed the ports, it might be that Restreamer Core restarted already, but it is now available on a different port.":"Jeśli zmieniłeś porty, Restreamer Core mógł już się zrestartować, ale jest teraz dostępny na innym porcie.","If you enabled Let's Encrypt TLS it might take some time to acquire the certificates. Make sure that Restreamer Core is reachable via port 80 from the internet. Please check the console log of Restreamer Core.":"Jeśli masz włączoną usługę Let's Encrypt TLS, uzyskanie certyfikatów może zająć trochę czasu. Upewnij się, że Restreamer Core jest dostępny przez port 80 z Internetu. Sprawdź dziennik konsoli Restreamer Core.","Ignore IP ranges":"Ignoruj ​​zakresy adresów IP","Image URL":"Link do obrazu","Imprint":"Wydrukowanie","In addition to the player, the Restreamer offers a complete landingpage, which you can use to present your live stream easily and quickly.":"Oprócz odtwarzacza, Restreamer oferuje obszerną stronę główną, na której możesz łatwo i szybko zaprezentować swoją transmisję na żywo.","In-memory":"W pamięci","In-memory storage":"Przechowywanie w pamięci","Incompatible":"Niezgodny","Inherit":"Odziedziczony od","Inject 1":"Wstrzyknij 1","Inject 2":"Wstrzyknij 2","Inject 3":"Wstrzyknij 3","Inject 4":"Wstrzyknij 4","Internal HLS server":"Wewnętrzny serwer HLS","Internal RTMP server":"Wewnętrzny serwer RTMP","Interval (seconds)":"Interwał (sekundy)","Issue alert":"Zgłoszenie problemów","Keyframe interval (seconds)":"Odstęp między klatkami kluczowymi (sekundy)","Layout":"Układ","Let's Encrypt certification":"Certyfikat Let's Encrypt","Let's Encrypt requires one or more public domain names and an accessible port 80/TCP.":"Let's Encrypt wymaga co najmniej jednej nazwy domeny publicznej i dostępnego portu 80/TCP.","Level":"Poziom","Level of system protocol.":"Poziom protokołu systemowego.","License":"Patent","Life color":"Kolor życia","Linecolor":"Kolor linii","Link":"Link","Link, mouseover":"Link, mouseover","List of IP ranges in CIDR notation, e.g., 127.0.0.1/32, that the statistics will not record—one IP range per line. Leave empty to record all sessions.":"Lista zakresów IP w notacji CIDR, na przykład 127.0.0.1/32, których statystyki nie będą rejestrowane - jeden zakres IP na linię. Pozostaw puste, aby zapisać wszystkie sesje.","List of file extensions to cache (e.g. \".html\"), one per line. Leave empty to cache all file types.":"Lista rozszerzeń plików do pamięci podręcznej (na przykład „.html”), po jednym w wierszu. Pozostaw puste, aby buforować wszystkie typy plików.","List size (segments)":"Rozmiar listy (segmenty)","Live-Streaming to Facebook Live RTMP service":"Przesyłanie strumieniowe na żywo do usługi Facebook Live RTMP","Live-Streaming to Instagram Live RTMP Service. The stream key requires a service such as <0>Yellow Duck.":"Usługa przesyłania strumieniowego na żywo RTMP na Instagramie Live. Klucz przesyłania strumieniowego wymaga usługi takiej jak <0>Yellow Duck.","Live-Streaming to Twitch Live RTMP Service.":"Transmisja na żywo w usłudze RTMP Twitch Live.","Live-Streaming to Vimeo Live RTMP Service":"Transmisja na żywo w usłudze Vimeos RTMP Live","Livesource ID":"Livesource ID","Log level":"Poziom dziennika","Logging":"Zapis","Login":"Zaloguj","Login failed: Couldn't load API details":"Połączenie nie powiodło się: nie udało się wczytać szczegółów interfejsu API","Login failed: {0}":["Połączenie nie powiodło się: ",["0"]],"Login/JWT authorization":"Zezwolenie na logowanie/JWT","Logo":"Logo","Logout":"Wyloguj","MB":"MB","Main Source":"Główne Źródło","Main channel":"Kanał główny","Main channel not found":"Nie znaleziono głównego kanału","Main channel saved":"Kanał główny zapisany","Main page channel (index.html).":"Kanał strony głównej (index.html).","Maintainer:":"Opiekun:","Maximum allowed cache size, 0 for unlimited.":"Maksymalny dozwolony rozmiar pamięci podręcznej, 0 nieograniczony.","Maximum allowed megabytes of RAM for /memfs, 0 for unlimited.":"Maksymalna dozwolona liczba megabajtów pamięci RAM dla /memfs, 0 oznacza nieograniczoną liczbę.","Maximum allowed megabytes to consume from hard disk. 0 for unlimited.":"Maksymalna dopuszczalna liczba megabajtów na dysku twardym. 0 dla nieograniczonego.","Maximum bandwidth Mbit/s":"Maksymalna przepustowość Mbit/s","Maximum delay in milliseconds.":"Maksymalne opóźnienie w milisekundach.","Maximum file size (Megabytes)":"Maksymalny rozmiar pliku (megabajty)","Maximum file size to put in cache.":"Taille maximale du fichier à mettre dans le cache.","Maximum log histroy":"Maksymalny dziennik historii","Maximum log lines":"Maksymalna liczba wierszy dziennika","Maximum size (Megabytes)":"Maksymalny rozmiar (MegaBajty)","Maximum viewer idle time (Seconds)":"Maksymalny czas bezczynności przeglądarki (sekundy)","Maximum viewers":"Maksymalna liczba widzów","Memory":"Pamięć","Meta information":"Informacje Meta","Metadata":"Metadane","Mold":"Pleśń","More about Twitter's copyright <0>here.":"Więcej informacji na temat praw autorskich Twittera <0>tutaj.","More about YouTube's copyright <0>here.":"Więcej informacji o prawach autorskich w YouTube <0>tutaj.","More about licenses here":"Więcej informacji o licencjach tutaj","More about the service":"Dowiedz się więcej o usłudze","Mute":"Wycisz","Name":"Nazwa","Name for the template. If the name already exists, it will be overwritten.":"Nazwa modelu. Jeśli nazwa już istnieje, zostanie nadpisana.","Network":"Sieć","Network source":"Źródło sieciowe","Next":"Następny","Next: Audio":"Następny: Dźwięk","Next: Video setup":"Dalej: Konfiguracja wideo","No":"Nie","No audio":"Bez dźwięku","No audio stream available":"Brak dostępnych strumieni audio","No input device available":"Brak dostępnego urządzenia wejściowego","No live stream was detected. Please check the software that sends the stream.":"Nie wykryto transmisji na żywo. Sprawdź oprogramowanie wysyłające strumień.","No source selected":"Nie wybrano źródła","No sources available":"Brak dostępnego źródła","No suitable encoder found.":"Nie znaleziono odpowiedniego enkodera.","No video":"Brak wideo","No video stream available":"Brak dostępnych strumieni wideo","Node ID":"Identyfikator węzła","Noise":"Dźwięk","None":"Żaden","Notes":"Notatki","Number of log lines to keep.":"Liczba wierszy dziennika do zachowania.","Number of logs to keep for each process.":"Liczba dzienników do przechowywania dla każdego procesu.","OK":"OK","One referrer per line, e.g. http://www.example.com":"Jedna strona odsyłająca w wierszu, na przykład http://www.domena.com.","Open":"Otwórz","Passthrough (copy) should only be disabled if necessary. Each encoding requires additional CPU/GPU resources.":"Przekazywanie (kopiowanie) powinno być wyłączone tylko w razie potrzeby. Każde kodowanie wymaga dodatkowych zasobów procesora/GPU.","Password":"Hasło","Password for authorization.":"Hasło do autoryzacji.","Password for the device.":"Hasło do urządzenia.","Persist viewer statistics":"Trwałość statystyk oglądających","Pixel format":"Proporcje pikseli","Plan: <0>Starter":"Schemat: <0>Starter","Platforms":"Platformy","Playback":"Odczyt","Player":"Player","Player URL":"Adres URL Playera","Player settings saved":"Zapis ustawień odtwarzacza","Playersite":"Playersite","Playlist":"Lista odtwarzania","Please check the <0>process log":"Sprawdź <0>Dziennik procesów.","Please contact the operator of the service and check what happens.":"Skontaktuj się z operatorem serwisu i sprawdź co się dzieje.","Please select a file to upload.":"Wybierz plik do przesłania.","Please use \"Passthrough (copy)\" if possible. Encoding requires additional CPU/GPU resources.":"Jeśli to możliwe, użyj opcji \"Przekazywanie (kopiowanie)”. Kodowanie wymaga dodatkowych zasobów procesora/GPU.","Please wait. Probe stream data ...":"Proszę czekać. Dane przepływu sondy...","Please wait. Setting up the stream ...":"Proszę czekać. Konfiguracja strumienia...","Port":"Port","Position":"Pozycja","Preset":"Zaprogramowane","Primary stream":"Główny stream","Primary stream key":"Klucz strumienia podstawowego","Probe":"Sonda","Process":"Przebieg","Process control":"Kontrola procesu","Process debug":"Debugowanie procesów","Process debug report":"Raport debugowania procesu","Process details":"Szczegóły procesu","Process report":"Raport z procesu","Processing & Control":"Przetwarzanie i kontrola","Profile":"Profil","Protocol":"Protokół","Protocols":"Protokoły","Public domain/s":"Domena(y) publiczna(e)","Publication service not found":"Nie znaleziono usługi wydawniczej","Publication website settings saved":"Tworzenie kopii zapasowej ustawień witryny publikacji","Publications":"Publikacje","Pull Mode":"Tryb ciągnięcia","Pull or recieve the data:":"Pobierz lub odbierz dane:","Quality":"Jakość","RGB test pattern":"Wzór testowy RGB","RTMP app for publishing.":"Aplikacja RTMP do publikacji.","RTMP server":"Serwer RTMP","RTMP server is not enabled":"Serwer RTMP nie jest włączony","RTMP server listen address.":"Adres nasłuchiwania serwera RTMP.","RTMP token for publishing and playing. The token is the value of the URL query parameter 'token.'":"Token RTMP do publikowania i odtwarzania. Token jest wartością parametru zapytania adresu URL \"token”.","RTMP/S":"RTMP/S","RTMPS server":"Serwer RTMPS","RTSP":"RTSP","Raspberry Pi camera":"Kamera Raspberry Pi","Rate control":"Kontrola szybkości","Ratio":"Ratio","Read input at native speed":"Odtwarzaj dane wejściowe z natywną prędkością","Receive Mode":"Tryb odbioru","Reconnect":"Połączyć ponownie","Reconnect delay (seconds)":"Limit czasu ponownego połączenia (sekundy)","Reconnecting in {0}s":["Połącz ponownie za ",["0"],"s"],"Reconnecting to Restreamer Core failed for the last {RETRIES} seconds.":["Ponowne połączenie z Restreamer Core nie powiodło się w ciągu ostatnich ",["RETRIES"]," sekund."],"Reconnecting to Restreamer Core failed.":"Nie udało się ponownie połączyć z Restreamer Core.","Refresh":"Odśwież","Region":"Region","Reload":"Odnów","Remove the oldest entries if the /memfs is full":"Usuń najstarsze wpisy, jeśli folder /memfs jest pełny","Requires activation":"Wymaga aktywacji","Restart":"Uruchom ponownie","Restart required":"Wymagane jest ponowne uruchomienie","Restarting":"Uruchom ponownie","Restarting Restreamer Core ...":"Uruchom ponownie Restreamer Core ...","Restarting the application failed.":"Ponowne uruchomienie aplikacji nie powiodło się.","Restreamer Service":"Usługa Restreamer","Retrieving stream data ...":"Pobieranie danych strumienia ...","Retry":"Spróbuj ponownie","Rule":"Reguła","Sampling":"Próbowanie","Save":"Zapisać","Scale":"Skala","Seconds to keep files in cache.":"Sekundy na przechowywanie plików w pamięci podręcznej.","Seconds until a process is restarted.":"Sekundy do ponownego uruchomienia procesu.","Seconds until a staled process is terminated.":"Sekundy do zakończenia zablokowanego procesu.","Seconds until the snapshot/thumbnail of the video source is updated.":"Sekundy do zaktualizowania migawki/miniaturki źródła wideo.","Security":"Bezpieczeństwo","Security token":"Token bezpieczeństwa","Seekbar color":"Kolor paska wyszukiwania (Seekbar)","Segment length (seconds)":"Długość segmentu (sekundy)","Segment will be cut on the following keyframe after this time has passed. 2 is recommended.":"Po upływie tego opóźnienia segment zostanie wycięty w następnej klatce kluczowej. Zalecana jest wartość 2.","Segmentation":"Segmentacja","Select a device:":"Wybierz urządzenie:","Select audio source:":"Wybierz źródło dźwięku:","Select source ...":"Wybierz źródło ...","Select video source:":"Wybierz źródło wideo:","Select whether you pull the stream from a <0>network source (such as a network camera) or the <1>internal RTMP server (e.g., OBS streams to the Restreamer).":"Wybierz, czy pobierasz strumień z <0>źródła sieciowego (np. kamery sieciowej), czy z <1>wewnętrznego serwera RTMP (np. strumienie OBS do Restreamer).","Select your encoding setting:":"Wybierz ustawienia kodowania:","Selected":"Wybrany","Selected channel":"Wybrany kanał","Selection":"Wybór","Send anonymous metrics (helps us for future development)":"Wysyłaj anonimowe dane (pomaga nam w przyszłym rozwoju)","Send stream to this address:":"Wyślij stream na ten adres:","Send video to Framebuffer":"Wyślij wideo do Framebuffer","Server":"Serwer","Service":"Usługa","Service name":"Nazwa serwisu","Service token for monitoring.":"Token serwisowy do monitorowania.","Sessions":"Sesje","Sets a bandwidth limit in Mbit per second for outgoing HLS data transfer. All services, such as RTMP and outgoing processes, are included in the calculation. If the bandwidth is exceeded, HLS viewers receive the HTTP status code 509 (Bandwidth Limit Exceeded). 0 is unlimited.":"Ustawia limit przepustowości w Mbit na sekundę dla wychodzącego transferu danych HLS. Wszystkie usługi, takie jak RTMP i procesy wychodzące, są uwzględniane w kalkulacji. W przypadku przekroczenia przepustowości przeglądarki HLS otrzymują kod stanu HTTP 509 (Przekroczono limit przepustowości). 0 jest nieograniczone.","Sets a viewer limit for HLS sessions. If the limit is exceeded, HLS viewers receive the HTTP status code 509 (Bandwidth Limit Exceeded). 0 is unlimited.":"Ustawia limit oglądania dla sesji HLS. W przypadku przekroczenia limitu przeglądarki HLS otrzymują kod stanu HTTP 509 (przekroczono limit przepustowości). Wartość 0 jest nieograniczona.","Setting for connection to the service.":"Parametr połączenia serwisowego.","Settings":"Ustawienia","Settings (expert mode)":"Parametry (tryb eksperta)","Settings for /data path. The access is protected by":"Parametry ścieżki /data. Dostęp jest chroniony przez","Settings for /memfs path.":"Parametry ścieżki /memfs.","Settings saved. All changes will be applied after restarting the application.":"Ustawienia zostały zapisane. Wszystkie zmiany zostaną zastosowane po ponownym uruchomieniu aplikacji.","Share button":"Przycisk udostępniania","Shows a reference to the project.":"Wyświetla odniesienie do projektu.","Sign up (free)":"Zarejestruj się (bezpłatnie)","Silence":"Cisza","Silence Audio":"Wycisz Dźwięk","Sine":"Sine","Sitename":"Nazwa Strony","Size":"Rozmiar","Snapshot":"Snapshot","Social-login (OAuth2, 2FA)":"Social-login (OAuth2, 2FA)","Socket timeout (microseconds)":"Limit czasu dla gniazd (mikrosekundy)","Software":"Oprogramowanie","Source":"Źródło","Speed":"Prędkość","Stale timeout (seconds)":"Limit czasu (sekundy)","Statistics":"Statystyki","Storage":"Magazynowanie","Stores the viewer statistics to the disk.":"Przechowuje statystyki oglądających na dysku.","Stream":"Stream","Stream URL":"Adres URL streamu","Stream key":"Klucz strumienia","Stream name":"Nazwa streamu","Stream names":"Nazwy stream","Support datarhei Restreamer":"Wsparcie datarhei Restreamer","Supports HTTP (HLS, DASH), RTP, RTSP, RTMP, SRT and more.":"Obsługuje HTTP (HLS, DASH), RTP, RTSP, RTMP, SRT i inne.","System":"System","Template":"Wygłąd","Template to be used for creating the publication website. The delete button removes the selection from the system.":"Szablon do wykorzystania przy tworzeniu strony internetowej publikacji. Przycisk Usuń usuwa zaznaczenie z systemu.","Terms":"Warunki","Test pattern":"Wzór testu","Test pattern (extended)":"Wzór testu (rozszerzony)","Text colors":"Kolory tekstu","The amplitude (0.0 - 1.0) of the generated audio stream":"Rozległość (0,0–1,0) generowanego strumienia audio","The application is using an older version of the settings.":"Aplikacja korzysta ze starej wersji ustawień.","The bitrate of the audio stream.":"Szybkość transmisji strumienia audio.","The carrier frequency":"Częstotliwość nośna","The channel \"{0}\" could not be deleted":["Nie można usunąć kanału \"",["0"],"”"],"The channel \"{0}\" has been deleted":["Kanał \"",["0"],"” został usunięty"],"The deletion of this channel can not be recovered. All publications of this channel will be removed.":"Usunięcia tego kanału nie można odzyskać. Wszystkie posty w tym kanale zostaną usunięte.","The input profile is not complete. Please define a video and audio source.":"Profil wpisu nie jest kompletny. Ustaw źródło wideo i audio.","The layout of the audio stream.":"Układ strumienia audio.","The maximum number of playlist segments. 0 will contain all the segments. 6 is recommended.":"Maksymalna liczba segmentów na liście odtwarzania. 0 będzie zawierało wszystkie segmenty. 6 jest zalecane.","The noise color":"Kolor szumu","The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.":"Osoba, która powiązała utwór z tym aktem, przekazała utwór do domeny publicznej, zrzekając się wszystkich praw do utworu na całym świecie zgodnie z prawem autorskim, w tym wszystkich praw pokrewnych i praw sąsiadów, w zakresie dozwolonym przez prawo. Możesz kopiować, modyfikować, rozpowszechniać i wykonywać pracę, nawet w celach komercyjnych, bez pytania o pozwolenie.","The public reachable domain name of the host this Restreamer is running on. Separate multiple domain names by a comma.":"Publiczna nazwa domeny hosta, na którym działa ten Restreamer. Poszczególne nazwy domen oddziel przecinkami.","The publication service \"{0}\" could not be deleted":["Nie można usunąć usługi publikowania \"",["0"],"”."],"The publication service \"{0}\" has been created":["Usługa publikowania \"",["0"],"” została utworzona."],"The publication service \"{0}\" has been deleted":["Usługa publikowania \"",["0"],"” została usunięta."],"The publication service has been created":"Powstał serwis wydawniczy","The sample rate of the audio stream.":"Częstotliwość próbkowania strumienia audio.","The selected file is too big ({0} bytes). Only {1} bytes are allowed.":["Wybrany plik jest za duży (",["0"]," bajtów). Dozwolonych jest tylko ",["1"]," bajtów."],"The selected file type ({0}) is not allowed. Allowed file types are {types}":["Wybrany typ pliku (",["0"],") jest niedozwolony. Dozwolone typy plików to ",["types"]],"The settings for \"{0}\" have been saved":["Ustawienia dla \"",["0"],"” zostały zapisane."],"The source doesn't provide any audio streams.":"Źródło nie zapewnia strumienia audio.","The source doesn't provide any audio streams. Please check the <0>probe details.":"Źródło nie zapewnia strumienia audio. Sprawdź <0>szczegóły sondy.","The source doesn't provide any compatible audio streams.":"Źródło nie zapewnia kompatybilnego strumienia audio.","The source doesn't provide any compatible video streams. Please check the <0>requirements.":"Źródło nie zapewnia kompatybilnego strumienia wideo. Sprawdź <0>wymagania.","The source doesn't provide any video streams. Please check the <0>probe details.":"Źródło nie zapewnia strumienia wideo. Sprawdź <0>szczegóły sondy.","The source doesn't provide any video streams. Please check the device.":"Źródło nie zapewnia strumienia wideo. Sprawdź urządzenie.","The video source doesn't provide any compatible audio stream. <0>Silence audio is recommended. Services e.g. YouTube, Facebook & Co. require an audio channel.":"Źródło wideo nie zapewnia kompatybilnego strumienia audio. Zalecana jest <0>wyciszenie dźwięku. Usługi takie jak YouTube, Facebook i Spółka wymagają kanału audio.","The video source is compatible. Select the desired resolution:":"Źródło wideo jest kompatybilne. Wybierz żądaną rozdzielczość:","There are updates available. Here you get more information.":"Dostępne są aktualizacje. Tutaj uzyskasz więcej informacji.","There was a problem storing the settings. Settings not saved.":"Podczas zapisywania ustawień wystąpił problem. Ustawienia nie zostały zapisane.","There was an error connecting to Restreamer Core at {0}.":["Wystąpił błąd podczas łączenia z Restreamer Core o ",["0"],"."],"There was an error during upload: {0}":["Wystąpił błąd podczas pobierania: ",["0"]],"There was an error setting up the stream.":"Wystąpił błąd podczas konfigurowania strumienia.","There were some errors in the settings. Settings not saved.":"Wystąpiły błędy w ustawieniach. Ustawienia nie zostały zapisane.","There's no login method available.":"Nie ma dostępnej metody połączenia.","This is a dummy service that explains to you the concepts of service.":"Jest to fikcyjna usługa, która wyjaśnia Ci koncepcje usługi.","This is not necessarily an error. However, it may take a bit longer for Restreamer Core to restart..":"Niekoniecznie jest to błąd. Jednak ponowne uruchomienie Restreamer Core może potrwać nieco dłużej...","This is to mention the copyright regulations for the target of this service.":"Ma to na celu wspomnieć o zasadach dotyczących praw autorskich dla celu tej usługi.","This license allows reusers to copy and distribute the material in any medium or format in unadapted form only, and only so long as attribution is given to the creator. The license allows for commercial use.":"Ta licencja umożliwia ponownemu użytkownikowi kopiowanie i rozpowszechnianie materiału w dowolnym medium lub formacie, wyłącznie w nieodpowiedniej formie, pod warunkiem, że twórca zostanie potwierdzony. Licencja pozwala na wykorzystanie komercyjne.","This license allows reusers to copy and distribute the material in any medium or format in unadapted form only, for noncommercial purposes only, and only so long as attribution is given to the creator.":"Niniejsza licencja umożliwia ponownemu kopiowaniu i rozpowszechnianiu materiału w dowolnym medium lub formacie, wyłącznie w nieodpowiedniej formie, do celów niekomercyjnych i pod warunkiem, że twórca zostanie potwierdzony.","This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format for noncommercial purposes only, and only so long as attribution is given to the creator.":"Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie wyłącznie do celów niekomercyjnych, pod warunkiem uznania autora za twórcę.","This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format for noncommercial purposes only, and only so long as attribution is given to the creator. If you remix, adapt, or build upon the material, you must license the modified material under identical terms.":"Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie wyłącznie do celów niekomercyjnych, pod warunkiem uznania autora za twórcę. Jeśli remiksujesz, adaptujesz lub rozszerzasz materiał, musisz licencjonować zmodyfikowany materiał na identycznych warunkach.","This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format, so long as attribution is given to the creator. The license allows for commercial use.":"Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie, pod warunkiem, że twórca zostanie potwierdzony. Licencja pozwala na wykorzystanie komercyjne.","This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format, so long as attribution is given to the creator. The license allows for commercial use. If you remix, adapt, or build upon the material, you must license the modified material under identical terms.":"Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie, pod warunkiem, że twórca zostanie potwierdzony. Licencja pozwala na wykorzystanie komercyjne. Jeśli remiksujesz, adaptujesz lub rozszerzasz materiał, musisz licencjonować zmodyfikowany materiał na identycznych warunkach.","This source cannot be edited while it is in use. To continue, you have to disconnect the source.":"Tego źródła nie można edytować podczas używania. Aby kontynuować, musisz odłączyć źródło.","This version of the UI doesn't support the available FFmpeg binary ({0}). The UI requires {1}. Please use a supported FFmpeg binary.":["Ta wersja interfejsu użytkownika nie obsługuje dostępnego pliku binarnego FFmpeg (",["0"],"). Interfejs użytkownika wymaga ",["1"],". Użyj obsługiwanego pliku binarnego FFmpeg."],"This version of the UI doesn't support the connected Core ({0}). The UI requires {1}. Please use a compatible version of the UI.":["Ta wersja interfejsu użytkownika nie obsługuje podłączonego Core (",["0"],"). Interfejs użytkownika wymaga ",["1"],". Użyj zgodnej wersji interfejsu użytkownika."],"This version of the UI is compatible.":"Ta wersja interfejsu użytkownika jest zgodna.","Time until an inactive viewer connection is treated as closed.":"Czas, po którym nieaktywne połączenie widza jest traktowane jako zamknięte.","Token":"Token","Transmit snapshots of the main source to an HTTP/S Server. More details about the settings can be found <0>here.":"Przesyłaj migawki z podstawowego źródła do serwera HTTP/S. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the audio channel of the main source to an Icecast Server. More details about the settings can be found <0>here.":"Przesyła kanał audio z głównego źródła do serwera Icecast. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source as HTTP-Live-Streaming (HLS) to an HTTP/S Server. More details about the settings can be found <0>here.":"Prześlij główne źródło jako HTTP-Live-Streaming (HLS) do serwera HTTP/S. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source as MPEG-DASH to an HTTP/S Server. More details about the settings can be found <0>here.":"Prześlij główne źródło w MPEG-DASH do serwera HTTP/S. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to a Brightcove Live Service. More details about the settings can be found <0>here.":"Prześlij główne źródło do usługi Brightcove Live. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to an CDN77 RTMP Service. More about the setup <0>here.":"Prześlij główne źródło do usługi CDN77 RTMP. Więcej informacji o konfiguracji <0>tutaj.","Transmit the main source to an DaCast RTMP Service. More about the setup <0>here.":"Prześlij główne źródło do usługi DaCast RTMP. Więcej informacji o konfiguracji <0>tutaj.","Transmit the main source to an MPEG-TS Service. More details about the settings can be found here <0>here.":"Prześlij główne źródło do usługi MPEG-TS. Więcej informacji na temat ustawień znajdziesz tutaj <0>tutaj.","Transmit the main source to an RTMP(e|s|t|te|ts) Server. More details about the settings can be found <0>here.":"Prześlij główne źródło do serwera RTMP(e|s|t|te|ts). Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to an RTSP Server. More details about the settings can be found <0>here.":"Prześlij główne źródło do serwera RTSP. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to an Red5/Pro Server. More details about the settings can be found <0>here.":"Prześlij główne źródło do serwera Red5/Pro. Więcej szczegółów na temat ustawień znajdziesz <0>tutaj.","Transmit the main source to an SRT Server. More details about the settings can be found <0>here.":"Prześlij główne źródło do serwera SRT. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to an UDP Server. More details about the settings can be found <0>here.":"Prześlij źródło podstawowe do serwera UDP. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to an WOWZA Server. More details about the settings can be found <0>here.":"Prześlij główne źródło do serwera WOWZA. Więcej szczegółów na temat ustawień znajdziesz <0>tutaj.","Transmit the main source to an datarhei Core Ressource. More details about the settings can be found <0>here.":"Przekaż źródło podstawowe do datarhei Core Ressource. Więcej szczegółów na temat ustawień można znaleźć <0>tutaj.","Transmit the main source to an livespotting.com Ressource. More details about the settings can be found <0>here.":"Przekaż główne źródło do Ressource livespotting.com. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to the Akamai (MSL) Media Services Live. More details about the MSL Encoder settings can be found on <0>here.":"Prześlij podstawowe źródło do usługi Akamai (MSL) Media Services Live. Więcej szczegółów na temat ustawień kodera MSL można znaleźć <0>tutaj.","Transmit the main source to the Bitmovin cloud encoding service, a powerful tool for live streaming. More details about the settings can be founds <0>here.":"Prześlij główne źródło do usługi kodowania w chmurze Bitmovin, potężnego narzędzia do przesyłania strumieniowego na żywo. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmit the main source to the Restream RTMP Service. More details about the settings can be found <0>here.":"Prześlij główne źródło do usługi Restream RTMP. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj.","Transmits your video as an RTMP stream with the required key generated in YouTube Studio. You can find more information on setting up a live stream at YouTube's <0>Creator Academy.":"Przesyła Twój film jako strumień RTMP z wymaganym kluczem wygenerowanym w YouTube Studio. Więcej informacji na temat konfigurowania transmisji na żywo znajdziesz w witrynie <0>Creator Academy YouTube.","Transmits your video stream with the required key, which was generated in Twitter Producer. You can find more information on seting up a live stream at Twitter's <0>Producer.":"Przesyła strumień wideo z wymaganym kluczem, który został wygenerowany w programie Twitter Producer. Więcej informacji na temat konfigurowania transmisji na żywo można znaleźć na stronie <0>Producent Twittera.","Tune":"Tune","UDP transport":"Transport UDP","Unable to load the config.":"Nie udało się wczytać konfiguracji.","Unique ident on the service.":"Unikalny identyfikator w usłudze.","Unknown":"Nieznany","Unselected":"Nie zaznaczone","Upload":"Upload","Uploading the file failed":"Przesyłanie pliku nie powiodło się","Uploading the logo failed":"Nie udało się pobrać logo","Uptime":"Czas operacyjny","Use Auth0 for your running Restreamer Core. More <0>details.":"Użyj Auth0 dla działającego Restreamera Core. Więcej <0>szczegółów.","Use the wizard (<0/>) for a quick and easy setup, or edit (<1/>) the sources directly in custom mode.":"Użyj kreatora (<0/>) do szybkiej i łatwej konfiguracji lub edytuj (<1/>) źródła bezpośrednio w trybie niestandardowym.","Use your copyright and choose the correct image license. Whether free for all or highly restricted. Briefly discuss what others are allowed to do with your image.":"Wykorzystaj swoje prawa autorskie i wybierz odpowiednią licencję na obraz. Bez względu na to, czy jest darmowy dla wszystkich, czy mocno ograniczony. Krótko omów, co inni mogą zrobić z Twoim wizerunkiem.","Use your copyright and choose the right image licence. Whether free for all or highly restricted. Briefly discuss what others are allowed to do with your image.":"Wykorzystaj swoje prawa autorskie i wybierz odpowiednią licencję na obraz. Niezależnie od tego, czy jest to licencja bezpłatna, czy bardzo ograniczona. Krótko omów, co inni mogą zrobić z Twoim wizerunkiem.","User registration":"Rejestracja Użytkownika","Username":"Login","Username for authorization.":"Nazwa użytkownika do autoryzacji.","Username for the device.":"Nazwa użytkownika urządzenia.","VPU ID":"VPU ID","Video":"Wideo","Video device":"Urządzenie wideo","Video settings":"Ustawienia wideo","Video setup":"Konfiguracja wideo","Video source":"Źródło wideo","Viewer":"Widz","Virtual source":"Wirtualne źródło","Welcome to Restreamer v2, the solution for fast and easy video publishing. Free for private and commercial use. Further help in the <0>docs.":"Witamy w Restreamer v2, rozwiązanie do szybkiego i łatwego publikowania filmów. Bezpłatnie do użytku prywatnego i komercyjnego. Więcej pomocy w <0>dokumentacji.","Write protection":"Ochrona przed zapisem","YUV test pattern":"Tabela testowa YUV","Yes":"Tak","You can't abort the wizard because at least one input must be defined.":"Nie można przerwać kreatora, ponieważ należy zdefiniować co najmniej jeden wpis.","You have changed the configuration. In order for the changes to take effect, you have to restart the application. Do you want to restart now?":"Zmieniłeś konfigurację. Aby zmiany odniosły skutek, musisz ponownie uruchomić aplikację. Czy chcesz teraz ponownie uruchomić?","You have to reconnect manually":"Musisz ponownie połączyć się ręcznie","You have unsaved changes. Please save them before you can control the service again.":"Masz niezapisane zmiany. Utwórz ich kopię zapasową, zanim będziesz mógł ponownie kontrolować usługę.","Your stream needs to be encoded, but there's no suitable encoder available.":"Twój strumień musi być zakodowany, ale nie jest dostępny odpowiedni koder.","Your stream needs to be encoded. Choose the desired encoder:":"Twój strumień musi być zakodowany. Wybierz żądany koder:","blue":"niebieski","brown":"brązowy","iframe code":"Kod iframe","kbit/s":"kbit/s","pink":"różowy","velvet":"aksamitny","violet":"fioletowy","white":"biały"}}; \ No newline at end of file diff --git a/src/locales/pl/messages.po b/src/locales/pl/messages.po new file mode 100644 index 0000000..af65d9e --- /dev/null +++ b/src/locales/pl/messages.po @@ -0,0 +1,2674 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: POEditor.com\n" +"Project-Id-Version: Restreamer\n" +"Language: pl\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#: src/misc/EncodingSelect.js:224 +msgid "<0>Compatibility list" +msgstr "<0>Lista kompatybilności" + +#: src/views/Edit/Profile.js:380 +#: src/views/Edit/Profile.js:510 +msgid "<0>Show probe details" +msgstr "<0>Pokaż szczegóły sondy" + +#: src/views/Edit/Sources/ALSA.js:156 +msgid "ALSA" +msgstr "ALSA" + +#: src/views/Settings.js:907 +msgid "API endpoint not found. Settings not saved." +msgstr "Nie znaleziono punktu końcowego interfejsu API. Ustawienia nie zostały zapisane." + +#: src/views/Edit/Sources/AVFoundation.js:221 +msgid "AVFoundation" +msgstr "AVFoundation" + +#: src/misc/ChannelList.js:356 +#: src/views/Edit/Profile.js:410 +#: src/views/Edit/Wizard/index.js:1153 +#: src/views/Edit/index.js:549 +#: src/views/Edit/index.js:575 +#: src/views/Edit/index.js:594 +#: src/views/Publication/Add.js:362 +#: src/views/Publication/Edit.js:601 +#: src/views/Settings.js:1972 +#: src/views/Settings.js:2031 +#: src/views/Settings.js:2053 +msgid "Abort" +msgstr "Anuluj" + +#: src/Header.js:283 +#: src/Header.js:324 +msgid "About" +msgstr "W związku z" + +#: src/misc/ChannelList.js:369 +msgid "Add" +msgstr "Dodaj" + +#: src/views/Publication/Add.js:321 +msgid "Add Publication" +msgstr "Dodaj Publikację" + +#: src/views/Playersite.js:692 +msgid "Add external widgets and styles to the publication site. You can find some examples on the help page." +msgstr "Dodaj widżety i style zewnętrzne do witryny publikowania. Kilka przykładów znajdziesz na stronie pomocy." + +#: src/misc/ChannelList.js:353 +msgid "Add new channel" +msgstr "Dodaj nowy kanał" + +#: src/views/Publication/Add.js:324 +msgid "Add: {0}" +msgstr "Dodaj : {0}" + +#: src/views/Edit/Sources/Network.js:355 +#: src/views/Edit/Wizard/Sources/Network.js:66 +#: src/views/Publication/Services/Brightcove.js:95 +#: src/views/Publication/Services/Core.js:100 +#: src/views/Publication/Services/DASH.js:192 +#: src/views/Publication/Services/HLS.js:181 +#: src/views/Publication/Services/Icecast.js:160 +#: src/views/Publication/Services/Image2.js:126 +#: src/views/Publication/Services/MPEGTS.js:160 +#: src/views/Publication/Services/RTMP.js:132 +#: src/views/Publication/Services/RTSP.js:150 +#: src/views/Publication/Services/Red5.js:115 +#: src/views/Publication/Services/SRT.js:161 +#: src/views/Publication/Services/UDP.js:127 +#: src/views/Publication/Services/WOWZA.js:132 +#: src/views/Settings.js:1302 +msgid "Address" +msgstr "Adres" + +#: src/views/Playersite.js:629 +msgid "Address for the background image." +msgstr "Adres obrazu tła." + +#: src/views/Settings.js:1331 +msgid "Address to listen on for HTTP requests." +msgstr "Adres do nasłuchiwania żądań HTTP." + +#: src/views/Settings.js:1344 +msgid "Address to listen on for HTTPS requests." +msgstr "Adres do nasłuchiwania żądań HTTPS." + +#: src/views/Playersite.js:514 +msgid "Adjust publication site colors and background as you like." +msgstr "Dostosuj kolory i tło witryny publikowania zgodnie z potrzebami." + +#: src/views/Login.js:322 +msgid "Advanced monitoring" +msgstr "Zaawansowane monitorowanie" + +#: src/views/Edit/Sources/Network.js:396 +#: src/views/Publication/Services/DASH.js:204 +#: src/views/Publication/Services/HLS.js:193 +#: src/views/Publication/Services/Icecast.js:170 +#: src/views/Publication/Services/Image2.js:132 +#: src/views/Publication/Services/MPEGTS.js:166 +#: src/views/Publication/Services/RTMP.js:138 +#: src/views/Publication/Services/RTSP.js:162 +#: src/views/Publication/Services/SRT.js:170 +#: src/views/Publication/Services/UDP.js:133 +msgid "Advanced settings" +msgstr "Zaawansowane ustawienia" + +#: src/views/Edit/Wizard/index.js:287 +msgid "Advanced setup" +msgstr "Ustawienia zaawansowane" + +#: src/views/Login.js:325 +msgid "Alerting by email" +msgstr "Powiadomienie e-mail" + +#: src/views/Publication/Add.js:344 +msgid "All" +msgstr "Wszystko" + +#: src/views/Settings.js:1163 +msgid "All important system settings." +msgstr "Wszystkie ważne parametry systemu." + +#: src/views/Settings.js:1478 +msgid "Allow all referrer" +msgstr "Zezwól wszystkim odsyłającym" + +#: src/views/Settings.js:1518 +msgid "Allow counting how many viewers the stream has." +msgstr "Pozwala policzyć liczbę widzów strumienia." + +#: src/views/Edit/Sources/VirtualAudio.js:126 +msgid "Amplitude" +msgstr "Zasięg" + +#: src/misc/Env.js:41 +msgid "An environment variable sets this value." +msgstr "Zmienna środowiskowa ustawia tę wartość." + +#: src/views/Publication/Services/Core.js:107 +#: src/views/Settings.js:1816 +msgid "App" +msgstr "App" + +#: src/Footer.js:218 +#: src/views/Publication/Services/Red5.js:126 +#: src/views/Publication/Services/WOWZA.js:148 +msgid "Application" +msgstr "Aplikacja" + +#: src/views/Edit/Wizard/index.js:1172 +msgid "Are you sure you want to abort the wizard?" +msgstr "Czy na pewno chcesz przerwać kreatorowi?" + +#: src/views/Publication/Add.js:492 +msgid "Audio" +msgstr "Dźwięk" + +#: src/views/Edit/Wizard/Sources/AVFoundation.js:111 +msgid "Audio Device" +msgstr "Urządzenie Dźwiękowe" + +#: src/views/Edit/Sources/ALSA.js:114 +#: src/views/Edit/Sources/AVFoundation.js:159 +msgid "Audio device" +msgstr "Urządzenie audio" + +#: src/views/Edit/Wizard/index.js:875 +#: src/views/Edit/Wizard/index.js:887 +msgid "Audio from device" +msgstr "Dźwięk z urządzenia" + +#: src/views/Edit/Profile.js:425 +#: src/views/Edit/ProfileSummary.js:90 +#: src/views/Publication/Edit.js:533 +msgid "Audio settings" +msgstr "Parametry dźwięku" + +#: src/views/Edit/Wizard/index.js:828 +msgid "Audio setup" +msgstr "Ustawienia dźwięku" + +#: src/views/Login.js:236 +msgid "Auth0" +msgstr "Auth0" + +#: src/views/Login.js:365 +msgid "Auth0 Tenant" +msgstr "Auth0 Najemca" + +#: src/views/Login.js:356 +msgid "Auth0 is currently not available because this interface is loaded from an insecure origin." +msgstr "Auth0 jest obecnie niedostępne, ponieważ ten interfejs jest ładowany z niezabezpieczonego źródła." + +#: src/misc/controls/Metadata.js:71 +msgid "Author" +msgstr "Autor" + +#: src/views/Settings.js:1143 +#: src/views/Settings.js:1415 +msgid "Authorization" +msgstr "Uprawnienie" + +#: src/misc/controls/HLS.js:83 +msgid "Automatic cleanup of all media data" +msgstr "Automatyczne czyszczenie wszystkich danych multimedialnych" + +#: src/views/Publication/Player.js:437 +msgid "Autoplay" +msgstr "Automatyczne odtwarzanie (Autoplay)" + +#: src/views/Playersite.js:445 +msgid "Available" +msgstr "Dostępne na" + +#: src/views/Edit/Profile.js:541 +#: src/views/Edit/Wizard/index.js:408 +#: src/views/Edit/Wizard/index.js:647 +#: src/views/Edit/Wizard/index.js:912 +#: src/views/Edit/Wizard/index.js:1024 +#: src/views/Edit/Wizard/index.js:1082 +#: src/views/Edit/Wizard/index.js:1164 +#: src/views/Publication/Add.js:528 +msgid "Back" +msgstr "Wstecz" + +#: src/views/Playersite.js:563 +msgid "Background colors" +msgstr "Kolory tła" + +#: src/views/Playersite.js:616 +msgid "Background image" +msgstr "Obraz tła" + +#: src/views/Publication/Services/Akamai.js:196 +msgid "Backup URL" +msgstr "Link do kopii zapasowej" + +#: src/views/Publication/Services/DaCast.js:182 +msgid "Backup server" +msgstr "Serwer kopii zapasowej" + +#: src/views/Publication/Services/Youtube.js:182 +msgid "Backup stream" +msgstr "Zapasowy stream" + +#: src/views/Publication/Services/Facebook.js:124 +msgid "Backup stream key" +msgstr "Klucz streamu kopii zapasowej" + +#: src/Footer.js:256 +#: src/Footer.js:269 +msgid "Bandwidth" +msgstr "Pasmo" + +#: src/views/Settings.js:1373 +msgid "Bandwidth control" +msgstr "Kontrola przepustowości" + +#: src/misc/modals/Process.js:81 +msgid "Banner" +msgstr "Baner" + +#: src/views/Login.js:241 +#: src/views/Settings.js:1420 +msgid "Basic" +msgstr "Zasadniczy" + +#: src/views/Edit/Sources/VirtualAudio.js:157 +msgid "Beep factor" +msgstr "Współczynnik sygnału dźwiękowego" + +#: src/misc/coders/settings/Audio.js:50 +#: src/misc/coders/settings/Video.js:51 +msgid "Bitrate" +msgstr "Bitrate" + +#: src/views/Edit/Wizard/index.js:1013 +#: src/views/Edit/index.js:510 +msgid "Briefly describe what the audience will see during the live stream." +msgstr "Krótko opisz, co widzowie zobaczą podczas transmisji na żywo." + +#: src/views/Publication/Player.js:352 +msgid "Button color" +msgstr "Kolor przycisku" + +#: src/views/Settings.js:1687 +msgid "Cache for files on /data." +msgstr "Buforowane pliki w /data." + +#: src/views/Settings.js:1715 +msgid "Cache time (Seconds)" +msgstr "Czas buforowania (w sekundach)" + +#: src/views/Settings.js:1743 +msgid "Cache types" +msgstr "Rodzaje buforu" + +#: src/views/Edit/Sources/AVFoundation.js:197 +msgid "Capture clicks" +msgstr "Przechwyt kliknięć" + +#: src/views/Edit/Sources/AVFoundation.js:194 +msgid "Capture cursor" +msgstr "Przechwyt kursoru" + +#: src/views/Edit/index.js:327 +msgid "Channel \"{0}\" saved" +msgstr "Kanał \"{0}” został zapisany" + +#: src/views/Edit/Sources/ALSA.js:129 +msgid "Channels" +msgstr "Kanały" + +#: src/views/Settings.js:1172 +msgid "Check for updates" +msgstr "Sprawdź aktualizacje" + +#: src/views/Publication/Add.js:272 +msgid "Check the requirements" +msgstr "Sprawdź wymagania" + +#: src/views/Edit/StreamSelect.js:53 +msgid "Choose a video stream" +msgstr "Wybierz strumień wideo" + +#: src/views/Edit/StreamSelect.js:68 +msgid "Choose an audio stream" +msgstr "Wybierz strumień dźwiękowy" + +#: src/views/Edit/Sources/ALSA.js:96 +#: src/views/Edit/Sources/Framebuffer.js:80 +#: src/views/Edit/Sources/Raspicam.js:84 +#: src/views/Edit/Sources/V4L.js:90 +msgid "Choose an input device ..." +msgstr "Wybierz urządzenie wejściowe ..." + +#: src/misc/EncodingSelect.js:202 +msgid "Choose codec ..." +msgstr "Wybierz kodek ..." + +#: src/views/Login.js:367 +msgid "Choose tenant ..." +msgstr "Wybór najemcy..." + +#: src/views/Publication/Services/DASH.js:309 +#: src/views/Publication/Services/HLS.js:249 +msgid "Chunk" +msgstr "Kawałek" + +#: src/misc/ModalContent.js:77 +#: src/views/Playersite.js:782 +#: src/views/Publication/Add.js:525 +#: src/views/Publication/Edit.js:565 +#: src/views/Publication/Player.js:447 +msgid "Close" +msgstr "Zamknij" + +#: src/views/Playersite.js:354 +msgid "Code injection" +msgstr "Wstrzyknięcie kodu" + +#: src/misc/EncodingSelect.js:200 +msgid "Codec" +msgstr "Kodek" + +#: src/views/Edit/Sources/VirtualAudio.js:110 +#: src/views/Publication/Player.js:320 +msgid "Color" +msgstr "Kolor" + +#: src/views/Settings.js:1282 +msgid "Config" +msgstr "Config" + +#: src/views/Password.js:117 +msgid "Confirm password" +msgstr "Potwierdź hasło" + +#: src/misc/ActionButton.js:38 +msgid "Connect" +msgstr "Zaloguj się" + +#: src/views/Edit/Wizard/Sources/AVFoundation.js:157 +msgid "Connected device" +msgstr "Urządzenie podłączone " + +#: src/views/Publication/Process.js:54 +msgid "Connected since <0/>" +msgstr "Zalogowany od " + +#: src/misc/ActionButton.js:12 +#: src/views/Main/index.js:305 +#: src/views/Publication/Process.js:40 +msgid "Connecting ..." +msgstr "Zalogowany ..." + +#: src/views/Initializing.js:21 +msgid "Connecting to Restreamer Core ..." +msgstr "Łączenie z Restreamer Core ..." + +#: src/views/Invalid.js:36 +msgid "Connecting to Restreamer Core failed probably because of mixed content." +msgstr "Połączenie z Restreamer Core nie powiodło się, prawdopodobnie z powodu mieszanej zawartości." + +#: src/misc/controls/Metadata.js:70 +#: src/views/Playersite.js:659 +#: src/views/Playersite.js:676 +msgid "Content" +msgstr "Zawartość" + +#: src/views/Main/index.js:365 +msgid "Content URL" +msgstr "" + +#: src/Footer.js:193 +msgid "Cores" +msgstr "Rdzenie" + +#: src/views/Password.js:127 +msgid "Create user" +msgstr "Utwórz użytkownika" + +#: src/misc/controls/License/index.js:112 +msgid "Creative Commons" +msgstr "Creative Commons" + +#: src/misc/coders/Encoders/audio/Opus.js:59 +#: src/misc/coders/settings/Audio.js:25 +#: src/misc/coders/settings/Audio.js:71 +#: src/misc/coders/settings/Audio.js:122 +#: src/misc/coders/settings/Video.js:31 +#: src/misc/coders/settings/Video.js:70 +#: src/misc/coders/settings/Video.js:115 +#: src/misc/coders/settings/Video.js:181 +#: src/misc/coders/settings/Video.js:220 +#: src/views/Edit/Sources/ALSA.js:101 +#: src/views/Edit/Sources/AVFoundation.js:120 +#: src/views/Edit/Sources/AVFoundation.js:153 +#: src/views/Edit/Sources/V4L.js:96 +msgid "Custom ..." +msgstr "Dostosuj ..." + +#: src/views/Settings.js:1288 +msgid "Custom JSON config for datarhei Core." +msgstr "Własna konfiguracja JSON dla Datarhei Core." + +#: src/views/Edit/Sources/ALSA.js:115 +msgid "Custom audio device" +msgstr "Własne urządzenie audio" + +#: src/views/Edit/Sources/AVFoundation.js:160 +msgid "Custom audio index" +msgstr "Własny indeks audio" + +#: src/misc/coders/settings/Audio.js:51 +#: src/misc/coders/settings/Video.js:52 +msgid "Custom bitrate (kbit/s)" +msgstr "Własna szybkość transmisji (kb/s)" + +#: src/views/Playersite.js:687 +msgid "Custom code injection" +msgstr "Wstrzyknięcie własnego kodu" + +#: src/misc/coders/Encoders/audio/Opus.js:85 +msgid "Custom delay" +msgstr "Własny limit czasu" + +#: src/views/Edit/Sources/Framebuffer.js:88 +msgid "Custom device" +msgstr "Własne urządzenie" + +#: src/misc/coders/settings/Video.js:241 +msgid "Custom format" +msgstr "Własny format" + +#: src/misc/coders/settings/Video.js:136 +msgid "Custom framerate" +msgstr "Własna częstotliwość odświeżania" + +#: src/misc/coders/settings/Video.js:91 +msgid "Custom keyframe interval" +msgstr "Własny interwał klatki kluczowej" + +#: src/misc/coders/settings/Audio.js:98 +msgid "Custom layout" +msgstr "Własny układ" + +#: src/misc/coders/settings/Audio.js:149 +msgid "Custom sampling (Hz)" +msgstr "Własne próbkowanie (Hz)" + +#: src/views/Edit/Sources/VirtualVideo.js:149 +msgid "Custom scale" +msgstr "Własna skala" + +#: src/misc/coders/settings/Video.js:202 +msgid "Custom size" +msgstr "Własny rozmiar" + +#: src/views/Edit/Sources/V4L.js:110 +msgid "Custom video device" +msgstr "Własne urządzenie wideo" + +#: src/views/Edit/Sources/AVFoundation.js:127 +msgid "Custom video index" +msgstr "Własny indeks wideo" + +#: src/misc/CopyButton.js:20 +#: src/misc/TextFieldCopy.js:33 +#: src/misc/Textarea.js:46 +msgid "Data copied to clipboard" +msgstr "Dane skopiowane do schowka" + +#: src/views/Edit/Sources/VirtualVideo.js:167 +msgid "Death color" +msgstr "Kolor śmierci" + +#: src/misc/EncodingSelect.js:210 +#: src/views/Edit/Wizard/index.js:628 +msgid "Decoder" +msgstr "Dekoder" + +#: src/views/Edit/Sources/AVFoundation.js:115 +#: src/views/Edit/Sources/AVFoundation.js:149 +#: src/views/Edit/Wizard/Sources/AVFoundation.js:76 +#: src/views/Edit/Wizard/Sources/AVFoundation.js:105 +#: src/views/Playersite.js:451 +#: src/views/Playersite.js:526 +#: src/views/Playersite.js:570 +msgid "Default" +msgstr "Domyślny" + +#: src/misc/coders/Encoders/audio/Opus.js:84 +msgid "Delay" +msgstr "Limit czasu" + +#: src/views/Edit/Sources/ALSA.js:132 +msgid "Delay (ms)" +msgstr "Opóźnienie (w ms)" + +#: src/views/Edit/index.js:563 +#: src/views/Edit/index.js:599 +#: src/views/Playersite.js:474 +#: src/views/Publication/Edit.js:574 +#: src/views/Publication/Edit.js:606 +msgid "Delete" +msgstr "Usuń" + +#: src/views/Publication/Edit.js:611 +msgid "Deleting a publication service cannot be reversed. The publication stops immediately." +msgstr "Usunięcia usługi publikowania nie można cofnąć. Publikowanie zatrzymuje się natychmiast." + +#: src/views/Publication/Services/Twitter.js:141 +#: src/views/Publication/Services/Youtube.js:167 +msgid "Delivering mode" +msgstr "Sposób dostawy" + +#: src/misc/controls/Metadata.js:85 +#: src/misc/controls/Metadata.js:110 +msgid "Description" +msgstr "Opis" + +#: src/views/Playersite.js:352 +#: src/views/Playersite.js:509 +msgid "Design" +msgstr "Model" + +#: src/views/Edit/Sources/Framebuffer.js:87 +#: src/views/Edit/Wizard/index.js:890 +#: src/views/Publication/Services/Framebuffer.js:93 +msgid "Device" +msgstr "Urządzenie" + +#: src/misc/ActionButton.js:24 +#: src/misc/ActionButton.js:45 +#: src/misc/ActionButton.js:59 +msgid "Disconnect" +msgstr "Wyloguj" + +#: src/views/Edit/index.js:580 +msgid "Disconnect & Continue" +msgstr "Odłącz i kontynuuj" + +#: src/misc/ActionButton.js:18 +#: src/views/Publication/Process.js:47 +msgid "Disconnecting ..." +msgstr "Wylogowywanie ..." + +#: src/views/Settings.js:1650 +msgid "Disk" +msgstr "Dysk" + +#: src/views/Settings.js:1684 +#: src/views/Settings.js:1692 +msgid "Disk cache" +msgstr "Dysk z pamięci podręcznej" + +#: src/Footer.js:315 +#: src/Footer.js:328 +msgid "Disk storage" +msgstr "Miejsce na dysku" + +#: src/views/Settings.js:2063 +msgid "Do you really want to restart the application now?" +msgstr "Czy na pewno chcesz teraz ponownie uruchomić aplikację?" + +#: src/views/Edit/index.js:591 +msgid "Do you want to delete \"{0}\"?" +msgstr "Czy chcesz usunąć \"{0}”?" + +#: src/views/Publication/Edit.js:598 +msgid "Do you want to delete {title}?" +msgstr "Czy chcesz usunąć {title}?" + +#: src/views/Edit/index.js:572 +msgid "Do you want to disconnect \"{0}\"?" +msgstr "Czy chcesz odłączyć \"{0}”?" + +#: src/Header.js:289 +#: src/Header.js:330 +msgid "Docs" +msgstr "Dokumenty" + +#: src/views/Publication/Services/DASH.js:501 +#: src/views/Publication/Services/HLS.js:496 +#: src/views/Publication/Services/Icecast.js:238 +#: src/views/Publication/Services/Image2.js:171 +#: src/views/Publication/Services/MPEGTS.js:355 +#: src/views/Publication/Services/RTMP.js:250 +#: src/views/Publication/Services/RTSP.js:235 +#: src/views/Publication/Services/SRT.js:428 +#: src/views/Publication/Services/UDP.js:241 +msgid "Documentation" +msgstr "Dokumentacja" + +#: src/misc/Progress.js:127 +msgid "Dup. frames" +msgstr "Ramki podwaniające" + +#: src/views/Publication/Player.js:285 +msgid "EDIT: Player" +msgstr "EDIT: Gracz" + +#: src/views/Playersite.js:346 +msgid "EDIT: Publication Website" +msgstr "EDIT: Witryna publikacji" + +#: src/views/Edit/index.js:391 +msgid "Edit" +msgstr "Edytuj" + +#: src/views/Edit/index.js:417 +msgid "Edit the audio and video sources for the live stream. Add a description, and set your desired content license." +msgstr "Zmień źródła audio i wideo dla transmisji na żywo. Dodaj opis i ustaw licencję na żądaną zawartość." + +#: src/views/Publication/Edit.js:377 +msgid "Edit: {title}" +msgstr "Edytuj: {title}" + +#: src/views/Publication/Player.js:319 +msgid "Embed" +msgstr "Integruj" + +#: src/views/Edit/Sources/Network.js:577 +#: src/views/Edit/Wizard/Sources/InternalRTMP.js:55 +msgid "Enable RTMP server ..." +msgstr "Aktywuj serwer RTMP ..." + +#: src/views/Edit/Sources/VirtualAudio.js:162 +msgid "Enable a periodic beep every second with this value times the carrier frequency" +msgstr "Aktywuje okresowy sygnał dźwiękowy co sekundę z tą wartością pomnożoną przez częstotliwość nośną" + +#: src/views/Publication/Services/Dummy.js:278 +#: src/views/Publication/Services/Facebook.js:139 +msgid "Enable backup stream" +msgstr "Aktywuj kopie streamu" + +#: src/views/Publication/Player.js:427 +msgid "Enable nerd statistics" +msgstr "Włącz statystyki nerdów" + +#: src/views/Publication/Services/Dummy.js:277 +#: src/views/Publication/Services/Facebook.js:138 +msgid "Enable primary stream" +msgstr "Aktywuj podstawowy stream" + +#: src/misc/controls/Snapshot.js:44 +msgid "Enable snapshots" +msgstr "Włącz migawki" + +#: src/views/Settings.js:1433 +msgid "Enabling authorization is strongly advised. Otherwise, anybody can access this instance." +msgstr "Zdecydowanie zaleca się aktywację autoryzacji. W przeciwnym razie każdy może uzyskać dostęp do tej instancji." + +#: src/views/Settings.js:1593 +msgid "Enabling basic auth is strongly advised. Otherwise, anybody could write data to /memfs." +msgstr "Zdecydowanie zaleca się włączenie uwierzytelniania podstawowego. W przeciwnym razie każdy mógłby zapisać dane do /memfs." + +#: src/views/Edit/Wizard/index.js:634 +msgid "Encoder" +msgstr "Koder" + +#: src/views/Edit/Summary.js:66 +#: src/views/Publication/Add.js:374 +#: src/views/Publication/Add.js:466 +#: src/views/Publication/Edit.js:388 +#: src/views/Publication/Edit.js:505 +msgid "Encoding" +msgstr "Kodowanie" + +#: src/views/Publication/Services/HLS.js:445 +#: src/views/Publication/Services/RTMP.js:222 +#: src/views/Publication/Services/SRT.js:372 +msgid "Encryption" +msgstr "Szyfrowanie" + +#: src/misc/ChannelList.js:376 +msgid "Enter a name for the new channel." +msgstr "Wpisz nazwę nowego kanału." + +#: src/views/Password.js:107 +msgid "Enter password" +msgstr "Wpisz hasło" + +#: src/views/Edit/Sources/Network.js:348 +#: src/views/Edit/Wizard/Sources/Network.js:59 +msgid "Enter the address of your network source:" +msgstr "Wprowadź adres źródła sieci:" + +#: src/views/Password.js:97 +msgid "Enter username" +msgstr "Wpisz login" + +#: src/misc/coders/Encoders/video/H264VideoToolbox.js:61 +msgid "Entropy coder" +msgstr "Koder entropii" + +#: src/views/Edit/Wizard/index.js:1118 +#: src/views/Incompatible.js:30 +#: src/views/Invalid.js:29 +#: src/views/Publication/Process.js:63 +#: src/views/Settings.js:1109 +msgid "Error" +msgstr "Błąd" + +#: src/misc/CopyButton.js:22 +#: src/misc/TextFieldCopy.js:35 +#: src/misc/Textarea.js:48 +msgid "Error while copying data to clipboard" +msgstr "Błąd podczas kopiowania danych do schowka" + +#: src/views/Main/index.js:324 +#: src/views/Publication/Process.js:64 +msgid "Error: {0}" +msgstr "Błąd: {0}" + +#: src/views/Playersite.js:732 +msgid "Expands the area above the channel list (live chat)." +msgstr "Rozwija obszar nad listą kanałów (czat na żywo)." + +#: src/views/Playersite.js:752 +msgid "Expands the area under the channel description (comment boxes)." +msgstr "Rozwija obszar pod opisem kanału (pola komentarzy)." + +#: src/views/Settings.js:1199 +msgid "Expert mode" +msgstr "Tryb ekspercki" + +#: src/views/Playersite.js:717 +msgid "Extend channel list" +msgstr "Rozwiń listę kanałów" + +#: src/views/Playersite.js:737 +msgid "Extend content" +msgstr "Rozwiń zawartość" + +#: src/views/Playersite.js:757 +msgid "Extend footer" +msgstr "Rozszerz stopkę" + +#: src/views/Playersite.js:697 +msgid "Extend header" +msgstr "Rozszerz nagłówek" + +#: src/views/Settings.js:1936 +msgid "FFmpeg" +msgstr "FFmpeg" + +#: src/misc/Progress.js:64 +#: src/views/Main/Progress.js:79 +msgid "FPS" +msgstr "FPS" + +#: src/views/Publication/Add.js:180 +msgid "Failed to create publication service ({0})" +msgstr "Nie udało się utworzyć usługi publikowania ({0})" + +#: src/views/Playersite.js:310 +msgid "Failed to create publication website files." +msgstr "Nie udało się utworzyć publikowanych plików witryny." + +#: src/views/Edit/Profile.js:341 +#: src/views/Edit/Profile.js:471 +msgid "Failed to probe the source. Please check the <0>probe details." +msgstr "Nie można zbadać źródła. Sprawdź <0>szczegóły sondy." + +#: src/utils/restreamer.js:434 +msgid "Failed to refresh token: {0}" +msgstr "Nie udało się odświeżyć tokena: {0}" + +#: src/views/Edit/index.js:304 +msgid "Failed to save ingest metadata" +msgstr "Nie udało się zapisać metadanych pozyskiwania" + +#: src/views/Edit/index.js:179 +msgid "Failed to stop process" +msgstr "Zakończenie procesu nie powiodło się" + +#: src/views/Playersite.js:303 +msgid "Failed to store player size setting." +msgstr "Nie udało się zapisać ustawienia rozmiaru dysku." + +#: src/views/Publication/Edit.js:222 +msgid "Failed to store publication service ({0})" +msgstr "Nie udało się zapisać usługi publikowania ({0})" + +#: src/views/Edit/index.js:297 +msgid "Failed to update ingest process ({0})" +msgstr "Nie udało się zaktualizować procesu przetwarzania ({0})" + +#: src/views/Edit/index.js:310 +msgid "Failed to update the player" +msgstr "Aktualizacja odtwarzacza nie powiodła się" + +#: src/views/Edit/Wizard/index.js:375 +#: src/views/Edit/Wizard/index.js:838 +msgid "Failed to verify the source. Please check the address." +msgstr "Nie można zweryfikować źródła. Zweryfikuj adres." + +#: src/views/Edit/Profile.js:549 +msgid "Finish" +msgstr "Wykończenie" + +#: src/views/Edit/Sources/VirtualVideo.js:182 +msgid "Flags" +msgstr "Flagi" + +#: src/views/Playersite.js:772 +msgid "For Javascripts." +msgstr "Dla JavaScriptów." + +#: src/views/Playersite.js:712 +msgid "For Stylesheets." +msgstr "Do arkuszy stylów." + +#: src/views/Edit/Sources/Network.js:439 +msgid "Force input framerate" +msgstr "Wymuś częstotliwość odświeżania wejściowego" + +#: src/misc/coders/settings/Video.js:240 +msgid "Format" +msgstr "Format" + +#: src/misc/Progress.js:114 +msgid "Frame drops" +msgstr "Spadki ramek" + +#: src/views/Edit/Sources/Framebuffer.js:129 +msgid "Framebuffer" +msgstr "Framebuffer" + +#: src/misc/coders/settings/Video.js:135 +#: src/views/Edit/Sources/Network.js:452 +msgid "Framerate" +msgstr "Częstotliwość wyświetlania klatek" + +#: src/views/Edit/Sources/VirtualAudio.js:145 +msgid "Frequency (Hz)" +msgstr "Częstotliwość (Hz)" + +#: src/views/Publication/Services/Core.js:129 +#: src/views/Publication/Services/Facebook.js:115 +#: src/views/Publication/Services/Facebook.js:133 +#: src/views/Publication/Services/Instagram.js:88 +#: src/views/Publication/Services/Restream.js:120 +#: src/views/Publication/Services/Twitch.js:133 +#: src/views/Publication/Services/Twitter.js:179 +#: src/views/Publication/Services/Youtube.js:177 +msgid "GET" +msgstr "GET" + +#: src/views/Edit/Sources/Network.js:471 +#: src/views/Edit/index.js:400 +#: src/views/Edit/index.js:412 +#: src/views/Playersite.js:350 +#: src/views/Playersite.js:363 +#: src/views/Publication/Add.js:372 +#: src/views/Publication/Edit.js:386 +#: src/views/Publication/Services/DASH.js:211 +#: src/views/Publication/Services/HLS.js:200 +#: src/views/Publication/Services/Icecast.js:177 +#: src/views/Publication/Services/Image2.js:139 +#: src/views/Publication/Services/RTMP.js:145 +#: src/views/Publication/Services/RTSP.js:169 +#: src/views/Publication/Services/SRT.js:177 +#: src/views/Settings.js:1138 +#: src/views/Settings.js:1158 +msgid "General" +msgstr "Główny" + +#: src/views/Publication/Player.js:410 +msgid "Google Analytics ID" +msgstr "Google Analytics ID" + +#: src/views/Publication/Player.js:420 +msgid "Google Analytics Tracker Name" +msgstr "Google Analytics Tracker Name" + +#: src/views/Edit/index.js:471 +#: src/views/Main/index.js:369 +msgid "HLS" +msgstr "HLS" + +#: src/views/Main/index.js:364 +#~ msgid "HLS URL" +#~ msgstr "Adres URL HLS" + +#: src/views/Settings.js:1510 +msgid "HLS statistic for the In-memory storage" +msgstr "Statystyki HLS dotyczące przechowywania w pamięci" + +#: src/views/Edit/Sources/Network.js:429 +msgid "HTTP and HTTPS" +msgstr "HTTP i HTTPS" + +#: src/views/Settings.js:1323 +msgid "HTTP port" +msgstr "Port HTTP" + +#: src/views/Settings.js:1352 +msgid "HTTPS (SSL/TLS)" +msgstr "HTTPS (SSL/TLS)" + +#: src/views/Settings.js:1336 +msgid "HTTPS port" +msgstr "Port HTTPS" + +#: src/views/Edit/Sources/V4L.js:151 +#: src/views/Edit/Wizard/Sources/V4L.js:140 +msgid "Hardware device" +msgstr "Urządzenie sprzętowe" + +#: src/views/Playersite.js:579 +msgid "Header" +msgstr "Nagłówek" + +#: src/views/Playersite.js:535 +msgid "Headline" +msgstr "Wyróżniony" + +#: src/views/Login.js:319 +msgid "Hosted Restreamer interface" +msgstr "Interfejs hostowany przez Restreamer" + +#: src/views/Settings.js:1258 +msgid "Human readable name on the service." +msgstr "Nazwa czytelna dla człowieka w usłudze." + +#: src/views/Publication/Services/Bitmovin.js:89 +msgid "IP address" +msgstr "Adres IP" + +#: src/views/Settings.js:2008 +msgid "If you changed the ports, it might be that Restreamer Core restarted already, but it is now available on a different port." +msgstr "Jeśli zmieniłeś porty, Restreamer Core mógł już się zrestartować, ale jest teraz dostępny na innym porcie." + +#: src/views/Settings.js:2002 +msgid "If you enabled Let's Encrypt TLS it might take some time to acquire the certificates. Make sure that Restreamer Core is reachable via port 80 from the internet. Please check the console log of Restreamer Core." +msgstr "Jeśli masz włączoną usługę Let's Encrypt TLS, uzyskanie certyfikatów może zająć trochę czasu. Upewnij się, że Restreamer Core jest dostępny przez port 80 z Internetu. Sprawdź dziennik konsoli Restreamer Core." + +#: src/views/Settings.js:1525 +msgid "Ignore IP ranges" +msgstr "Ignoruj ​​zakresy adresów IP" + +#: src/views/Playersite.js:624 +#: src/views/Publication/Player.js:366 +msgid "Image URL" +msgstr "Link do obrazu" + +#: src/views/Playersite.js:649 +msgid "Imprint" +msgstr "Wydrukowanie" + +#: src/views/Playersite.js:368 +msgid "In addition to the player, the Restreamer offers a complete landingpage, which you can use to present your live stream easily and quickly." +msgstr "Oprócz odtwarzacza, Restreamer oferuje obszerną stronę główną, na której możesz łatwo i szybko zaprezentować swoją transmisję na żywo." + +#: src/views/Settings.js:1577 +msgid "In-memory" +msgstr "W pamięci" + +#: src/Footer.js:285 +#: src/Footer.js:298 +msgid "In-memory storage" +msgstr "Przechowywanie w pamięci" + +#: src/views/Publication/Add.js:269 +msgid "Incompatible" +msgstr "Niezgodny" + +#: src/misc/coders/settings/Audio.js:67 +#: src/misc/coders/settings/Audio.js:118 +msgid "Inherit" +msgstr "Odziedziczony od" + +#: src/views/Playersite.js:707 +msgid "Inject 1" +msgstr "Wstrzyknij 1" + +#: src/views/Playersite.js:727 +msgid "Inject 2" +msgstr "Wstrzyknij 2" + +#: src/views/Playersite.js:747 +msgid "Inject 3" +msgstr "Wstrzyknij 3" + +#: src/views/Playersite.js:767 +msgid "Inject 4" +msgstr "Wstrzyknij 4" + +#: src/views/Edit/Wizard/Sources/InternalHLS.js:75 +msgid "Internal HLS server" +msgstr "Wewnętrzny serwer HLS" + +#: src/views/Edit/Wizard/Sources/InternalRTMP.js:95 +msgid "Internal RTMP server" +msgstr "Wewnętrzny serwer RTMP" + +#: src/misc/controls/Snapshot.js:50 +msgid "Interval (seconds)" +msgstr "Interwał (sekundy)" + +#: src/Header.js:295 +#: src/Header.js:336 +msgid "Issue alert" +msgstr "Zgłoszenie problemów" + +#: src/misc/coders/settings/Video.js:90 +msgid "Keyframe interval (seconds)" +msgstr "Odstęp między klatkami kluczowymi (sekundy)" + +#: src/misc/coders/settings/Audio.js:97 +msgid "Layout" +msgstr "Układ" + +#: src/views/Settings.js:1357 +msgid "Let's Encrypt certification" +msgstr "Certyfikat Let's Encrypt" + +#: src/views/Settings.js:1365 +msgid "Let's Encrypt requires one or more public domain names and an accessible port 80/TCP." +msgstr "Let's Encrypt wymaga co najmniej jednej nazwy domeny publicznej i dostępnego portu 80/TCP." + +#: src/misc/coders/Encoders/video/H264NVENC.js:109 +msgid "Level" +msgstr "Poziom" + +#: src/views/Settings.js:1918 +msgid "Level of system protocol." +msgstr "Poziom protokołu systemowego." + +#: src/views/Edit/Wizard/index.js:1061 +#: src/views/Edit/index.js:403 +#: src/views/Edit/index.js:525 +msgid "License" +msgstr "Patent" + +#: src/views/Edit/Sources/VirtualVideo.js:176 +msgid "Life color" +msgstr "Kolor życia" + +#: src/views/Playersite.js:606 +msgid "Linecolor" +msgstr "Kolor linii" + +#: src/views/Playersite.js:544 +#: src/views/Publication/Player.js:396 +msgid "Link" +msgstr "Link" + +#: src/views/Playersite.js:553 +msgid "Link, mouseover" +msgstr "Link, mouseover" + +#: src/views/Settings.js:1533 +msgid "List of IP ranges in CIDR notation, e.g., 127.0.0.1/32, that the statistics will not record—one IP range per line. Leave empty to record all sessions." +msgstr "Lista zakresów IP w notacji CIDR, na przykład 127.0.0.1/32, których statystyki nie będą rejestrowane - jeden zakres IP na linię. Pozostaw puste, aby zapisać wszystkie sesje." + +#: src/views/Settings.js:1751 +msgid "List of file extensions to cache (e.g. \".html\"), one per line. Leave empty to cache all file types." +msgstr "Lista rozszerzeń plików do pamięci podręcznej (na przykład „.html”), po jednym w wierszu. Pozostaw puste, aby buforować wszystkie typy plików." + +#: src/misc/controls/HLS.js:74 +msgid "List size (segments)" +msgstr "Rozmiar listy (segmenty)" + +#: src/views/Publication/Services/Facebook.js:16 +msgid "Live-Streaming to Facebook Live RTMP service" +msgstr "Przesyłanie strumieniowe na żywo do usługi Facebook Live RTMP" + +#: src/views/Publication/Services/Instagram.js:17 +msgid "Live-Streaming to Instagram Live RTMP Service. The stream key requires a service such as <0>Yellow Duck." +msgstr "Usługa przesyłania strumieniowego na żywo RTMP na Instagramie Live. Klucz przesyłania strumieniowego wymaga usługi takiej jak <0>Yellow Duck." + +#: src/views/Publication/Services/Twitch.js:17 +msgid "Live-Streaming to Twitch Live RTMP Service." +msgstr "Transmisja na żywo w usłudze RTMP Twitch Live." + +#: src/views/Publication/Services/Vimeo.js:12 +msgid "Live-Streaming to Vimeo Live RTMP Service" +msgstr "Transmisja na żywo w usłudze Vimeos RTMP Live" + +#: src/views/Publication/Services/Livespotting.js:94 +msgid "Livesource ID" +msgstr "Livesource ID" + +#: src/views/Settings.js:1870 +msgid "Log level" +msgstr "Poziom dziennika" + +#: src/misc/modals/Process.js:90 +#: src/views/Settings.js:1147 +#: src/views/Settings.js:1846 +msgid "Logging" +msgstr "Zapis" + +#: src/views/Login.js:297 +#: src/views/Login.js:391 +#: src/views/Login.js:406 +#: src/views/Publication/Services/Akamai.js:124 +msgid "Login" +msgstr "Zaloguj" + +#: src/utils/restreamer.js:263 +#: src/utils/restreamer.js:268 +#: src/utils/restreamer.js:297 +#: src/utils/restreamer.js:302 +msgid "Login failed: Couldn't load API details" +msgstr "Połączenie nie powiodło się: nie udało się wczytać szczegółów interfejsu API" + +#: src/utils/restreamer.js:254 +#: src/utils/restreamer.js:288 +msgid "Login failed: {0}" +msgstr "Połączenie nie powiodło się: {0}" + +#: src/views/Settings.js:1425 +msgid "Login/JWT authorization" +msgstr "Zezwolenie na logowanie/JWT" + +#: src/views/Publication/Player.js:321 +msgid "Logo" +msgstr "Logo" + +#: src/Header.js:307 +msgid "Logout" +msgstr "Wyloguj" + +#: src/Footer.js:208 +msgid "MB" +msgstr "MB" + +#: src/views/Edit/index.js:380 +msgid "Main Source" +msgstr "Główne Źródło" + +#: src/views/Main/index.js:260 +#: src/views/Playersite.js:389 +msgid "Main channel" +msgstr "Kanał główny" + +#: src/views/Publication/Player.js:102 +msgid "Main channel not found" +msgstr "Nie znaleziono głównego kanału" + +#: src/views/Edit/Wizard/index.js:188 +msgid "Main channel saved" +msgstr "Kanał główny zapisany" + +#: src/views/Playersite.js:412 +msgid "Main page channel (index.html)." +msgstr "Kanał strony głównej (index.html)." + +#: src/views/Publication/Add.js:411 +#: src/views/Publication/Add.js:444 +#: src/views/Publication/Add.js:511 +#: src/views/Publication/Edit.js:419 +#: src/views/Publication/Edit.js:483 +#: src/views/Publication/Edit.js:552 +msgid "Maintainer:" +msgstr "Opiekun:" + +#: src/views/Settings.js:1710 +msgid "Maximum allowed cache size, 0 for unlimited." +msgstr "Maksymalny dozwolony rozmiar pamięci podręcznej, 0 nieograniczony." + +#: src/views/Settings.js:1632 +msgid "Maximum allowed megabytes of RAM for /memfs, 0 for unlimited." +msgstr "Maksymalna dozwolona liczba megabajtów pamięci RAM dla /memfs, 0 oznacza nieograniczoną liczbę." + +#: src/views/Settings.js:1676 +msgid "Maximum allowed megabytes to consume from hard disk. 0 for unlimited." +msgstr "Maksymalna dopuszczalna liczba megabajtów na dysku twardym. 0 dla nieograniczonego." + +#: src/views/Settings.js:1394 +msgid "Maximum bandwidth Mbit/s" +msgstr "Maksymalna przepustowość Mbit/s" + +#: src/misc/coders/Encoders/audio/Opus.js:74 +msgid "Maximum delay in milliseconds." +msgstr "Maksymalne opóźnienie w milisekundach." + +#: src/views/Settings.js:1728 +msgid "Maximum file size (Megabytes)" +msgstr "Maksymalny rozmiar pliku (megabajty)" + +#: src/views/Settings.js:1736 +msgid "Maximum file size to put in cache." +msgstr "Taille maximale du fichier à mettre dans le cache." + +#: src/views/Settings.js:1954 +msgid "Maximum log histroy" +msgstr "Maksymalny dziennik historii" + +#: src/views/Settings.js:1923 +#: src/views/Settings.js:1941 +msgid "Maximum log lines" +msgstr "Maksymalna liczba wierszy dziennika" + +#: src/views/Settings.js:1624 +#: src/views/Settings.js:1668 +#: src/views/Settings.js:1702 +msgid "Maximum size (Megabytes)" +msgstr "Maksymalny rozmiar (MegaBajty)" + +#: src/views/Settings.js:1542 +msgid "Maximum viewer idle time (Seconds)" +msgstr "Maksymalny czas bezczynności przeglądarki (sekundy)" + +#: src/views/Settings.js:1378 +msgid "Maximum viewers" +msgstr "Maksymalna liczba widzów" + +#: src/Footer.js:202 +msgid "Memory" +msgstr "Pamięć" + +#: src/views/Edit/index.js:402 +msgid "Meta information" +msgstr "Informacje Meta" + +#: src/views/Edit/Wizard/index.js:1006 +#: src/views/Edit/index.js:505 +msgid "Metadata" +msgstr "Metadane" + +#: src/views/Edit/Sources/VirtualVideo.js:158 +msgid "Mold" +msgstr "Pleśń" + +#: src/views/Publication/Services/Twitter.js:30 +msgid "More about Twitter's copyright <0>here." +msgstr "Więcej informacji na temat praw autorskich Twittera <0>tutaj." + +#: src/views/Publication/Services/Youtube.js:31 +msgid "More about YouTube's copyright <0>here." +msgstr "Więcej informacji o prawach autorskich w YouTube <0>tutaj." + +#: src/views/Publication/Services/Facebook.js:17 +#: src/views/Publication/Services/Twitch.js:18 +#: src/views/Publication/Services/Vimeo.js:14 +msgid "More about licenses here" +msgstr "Więcej informacji o licencjach tutaj" + +#: src/views/Settings.js:1227 +msgid "More about the service" +msgstr "Dowiedz się więcej o usłudze" + +#: src/views/Publication/Player.js:438 +msgid "Mute" +msgstr "Wycisz" + +#: src/misc/ChannelList.js:380 +#: src/misc/controls/Metadata.js:76 +#: src/misc/controls/Metadata.js:98 +#: src/views/Playersite.js:489 +#: src/views/Settings.js:1250 +msgid "Name" +msgstr "Nazwa" + +#: src/views/Playersite.js:494 +msgid "Name for the template. If the name already exists, it will be overwritten." +msgstr "Nazwa modelu. Jeśli nazwa już istnieje, zostanie nadpisana." + +#: src/views/Settings.js:1142 +#: src/views/Settings.js:1297 +msgid "Network" +msgstr "Sieć" + +#: src/views/Edit/Sources/Network.js:684 +#: src/views/Edit/Wizard/Sources/Network.js:110 +msgid "Network source" +msgstr "Źródło sieciowe" + +#: src/views/Edit/Wizard/index.js:413 +#: src/views/Edit/Wizard/index.js:652 +#: src/views/Edit/Wizard/index.js:917 +#: src/views/Edit/Wizard/index.js:1029 +msgid "Next" +msgstr "Następny" + +#: src/views/Edit/Profile.js:413 +msgid "Next: Audio" +msgstr "Następny: Dźwięk" + +#: src/views/Welcome.js:39 +msgid "Next: Video setup" +msgstr "Dalej: Konfiguracja wideo" + +#: src/views/Edit/Wizard/index.js:1182 +msgid "No" +msgstr "Nie" + +#: src/views/Edit/Sources/NoAudio.js:45 +#: src/views/Edit/Wizard/index.js:901 +msgid "No audio" +msgstr "Bez dźwięku" + +#: src/views/Edit/StreamSelect.js:62 +msgid "No audio stream available" +msgstr "Brak dostępnych strumieni audio" + +#: src/views/Edit/Wizard/Sources/AVFoundation.js:70 +#: src/views/Edit/Wizard/Sources/V4L.js:99 +msgid "No input device available" +msgstr "Brak dostępnego urządzenia wejściowego" + +#: src/views/Edit/Wizard/index.js:373 +msgid "No live stream was detected. Please check the software that sends the stream." +msgstr "Nie wykryto transmisji na żywo. Sprawdź oprogramowanie wysyłające strumień." + +#: src/views/Edit/Summary.js:28 +msgid "No source selected" +msgstr "Nie wybrano źródła" + +#: src/views/Edit/SourceSelect.js:174 +msgid "No sources available" +msgstr "Brak dostępnego źródła" + +#: src/misc/EncodingSelect.js:164 +msgid "No suitable encoder found." +msgstr "Nie znaleziono odpowiedniego enkodera." + +#: src/views/Main/index.js:286 +#: src/views/Publication/Player.js:294 +msgid "No video" +msgstr "Brak wideo" + +#: src/views/Edit/StreamSelect.js:47 +msgid "No video stream available" +msgstr "Brak dostępnych strumieni wideo" + +#: src/views/Settings.js:1243 +msgid "Node ID" +msgstr "Identyfikator węzła" + +#: src/views/Edit/Sources/VirtualAudio.js:90 +msgid "Noise" +msgstr "Dźwięk" + +#: src/views/Edit/Sources/AVFoundation.js:145 +#: src/views/Edit/Summary.js:30 +#: src/views/Edit/Wizard/Sources/AVFoundation.js:98 +msgid "None" +msgstr "Żaden" + +#: src/views/Playersite.js:353 +#: src/views/Playersite.js:644 +msgid "Notes" +msgstr "Notatki" + +#: src/views/Settings.js:1931 +#: src/views/Settings.js:1949 +msgid "Number of log lines to keep." +msgstr "Liczba wierszy dziennika do zachowania." + +#: src/views/Settings.js:1962 +msgid "Number of logs to keep for each process." +msgstr "Liczba dzienników do przechowywania dla każdego procesu." + +#: src/views/Playersite.js:813 +#: src/views/Publication/Player.js:466 +msgid "OK" +msgstr "OK" + +#: src/views/Settings.js:1497 +msgid "One referrer per line, e.g. http://www.example.com" +msgstr "Jedna strona odsyłająca w wierszu, na przykład http://www.domena.com." + +#: src/views/Playersite.js:798 +msgid "Open" +msgstr "Otwórz" + +#: src/views/Publication/Edit.js:510 +msgid "Passthrough (copy) should only be disabled if necessary. Each encoding requires additional CPU/GPU resources." +msgstr "Przekazywanie (kopiowanie) powinno być wyłączone tylko w razie potrzeby. Każde kodowanie wymaga dodatkowych zasobów procesora/GPU." + +#: src/views/Edit/Sources/Network.js:382 +#: src/views/Edit/Wizard/Sources/Network.js:88 +#: src/views/Login.js:282 +#: src/views/Publication/Services/Akamai.js:134 +#: src/views/Publication/Services/DASH.js:198 +#: src/views/Publication/Services/DaCast.js:142 +#: src/views/Publication/Services/HLS.js:187 +#: src/views/Publication/Services/RTSP.js:156 +#: src/views/Publication/Services/Red5.js:157 +#: src/views/Publication/Services/WOWZA.js:178 +#: src/views/Settings.js:1453 +#: src/views/Settings.js:1611 +msgid "Password" +msgstr "Hasło" + +#: src/views/Settings.js:1459 +#: src/views/Settings.js:1619 +msgid "Password for authorization." +msgstr "Hasło do autoryzacji." + +#: src/views/Edit/Sources/Network.js:387 +#: src/views/Edit/Wizard/Sources/Network.js:90 +msgid "Password for the device." +msgstr "Hasło do urządzenia." + +#: src/views/Settings.js:1555 +msgid "Persist viewer statistics" +msgstr "Trwałość statystyk oglądających" + +#: src/views/Publication/Services/Framebuffer.js:102 +msgid "Pixel format" +msgstr "Proporcje pikseli" + +#: src/views/Login.js:311 +msgid "Plan: <0>Starter" +msgstr "Schemat: <0>Starter" + +#: src/views/Publication/Add.js:347 +msgid "Platforms" +msgstr "Platformy" + +#: src/views/Publication/Player.js:323 +#: src/views/Settings.js:1144 +#: src/views/Settings.js:1468 +msgid "Playback" +msgstr "Odczyt" + +#: src/views/Main/Egress.js:95 +msgid "Player" +msgstr "Player" + +#: src/views/Publication/Player.js:328 +msgid "Player URL" +msgstr "Adres URL Playera" + +#: src/views/Publication/Player.js:257 +msgid "Player settings saved" +msgstr "Zapis ustawień odtwarzacza" + +#: src/Header.js:267 +#: src/views/Playersite.js:375 +msgid "Playersite" +msgstr "Playersite" + +#: src/views/Publication/Services/DASH.js:348 +#: src/views/Publication/Services/HLS.js:288 +msgid "Playlist" +msgstr "Lista odtwarzania" + +#: src/views/Main/index.js:329 +msgid "Please check the <0>process log" +msgstr "Sprawdź <0>Dziennik procesów." + +#: src/views/Publication/Services/Akamai.js:29 +#: src/views/Publication/Services/Bitmovin.js:23 +#: src/views/Publication/Services/Brightcove.js:23 +#: src/views/Publication/Services/CDN77.js:23 +#: src/views/Publication/Services/Core.js:26 +#: src/views/Publication/Services/DASH.js:35 +#: src/views/Publication/Services/DaCast.js:26 +#: src/views/Publication/Services/HLS.js:37 +#: src/views/Publication/Services/Icecast.js:29 +#: src/views/Publication/Services/Image2.js:33 +#: src/views/Publication/Services/Livespotting.js:23 +#: src/views/Publication/Services/MPEGTS.js:35 +#: src/views/Publication/Services/RTMP.js:32 +#: src/views/Publication/Services/RTSP.js:36 +#: src/views/Publication/Services/Red5.js:25 +#: src/views/Publication/Services/Restream.js:26 +#: src/views/Publication/Services/SRT.js:33 +#: src/views/Publication/Services/UDP.js:31 +#: src/views/Publication/Services/WOWZA.js:28 +msgid "Please contact the operator of the service and check what happens." +msgstr "Skontaktuj się z operatorem serwisu i sprawdź co się dzieje." + +#: src/views/Playersite.js:122 +#: src/views/Playersite.js:197 +#: src/views/Publication/Player.js:159 +msgid "Please select a file to upload." +msgstr "Wybierz plik do przesłania." + +#: src/views/Publication/Add.js:471 +msgid "Please use \"Passthrough (copy)\" if possible. Encoding requires additional CPU/GPU resources." +msgstr "Jeśli to możliwe, użyj opcji \"Przekazywanie (kopiowanie)”. Kodowanie wymaga dodatkowych zasobów procesora/GPU." + +#: src/views/Edit/Wizard/index.js:435 +#: src/views/Edit/Wizard/index.js:933 +msgid "Please wait. Probe stream data ..." +msgstr "Proszę czekać. Dane przepływu sondy..." + +#: src/views/Edit/Wizard/index.js:1103 +msgid "Please wait. Setting up the stream ..." +msgstr "Proszę czekać. Konfiguracja strumienia..." + +#: src/views/Publication/Services/Bitmovin.js:92 +#: src/views/Settings.js:1803 +msgid "Port" +msgstr "Port" + +#: src/views/Publication/Player.js:381 +msgid "Position" +msgstr "Pozycja" + +#: src/misc/coders/Encoders/video/H264NVENC.js:67 +#: src/misc/coders/Encoders/video/X264.js:62 +#: src/misc/coders/Encoders/video/X265.js:62 +msgid "Preset" +msgstr "Zaprogramowane" + +#: src/views/Publication/Services/Youtube.js:181 +msgid "Primary stream" +msgstr "Główny stream" + +#: src/views/Publication/Services/Facebook.js:106 +msgid "Primary stream key" +msgstr "Klucz strumienia podstawowego" + +#: src/views/Edit/Sources/ALSA.js:136 +#: src/views/Edit/Sources/AVFoundation.js:201 +#: src/views/Edit/Sources/Framebuffer.js:110 +#: src/views/Edit/Sources/Network.js:505 +#: src/views/Edit/Sources/Network.js:552 +#: src/views/Edit/Sources/Network.js:599 +#: src/views/Edit/Sources/Raspicam.js:113 +#: src/views/Edit/Sources/V4L.js:131 +#: src/views/Edit/Sources/VirtualAudio.js:169 +#: src/views/Edit/Sources/VirtualVideo.js:188 +msgid "Probe" +msgstr "Sonda" + +#: src/views/Edit/index.js:493 +#: src/views/Publication/Add.js:433 +#: src/views/Publication/Edit.js:441 +msgid "Process" +msgstr "Przebieg" + +#: src/views/Publication/Add.js:373 +#: src/views/Publication/Edit.js:387 +msgid "Process control" +msgstr "Kontrola procesu" + +#: src/views/Publication/Edit.js:471 +msgid "Process debug" +msgstr "Debugowanie procesów" + +#: src/views/Main/index.js:413 +#: src/views/Publication/Edit.js:591 +msgid "Process debug report" +msgstr "Raport debugowania procesu" + +#: src/views/Main/index.js:389 +#: src/views/Main/index.js:405 +#: src/views/Publication/Edit.js:468 +#: src/views/Publication/Edit.js:583 +msgid "Process details" +msgstr "Szczegóły procesu" + +#: src/views/Main/index.js:392 +msgid "Process report" +msgstr "Raport z procesu" + +#: src/views/Edit/index.js:401 +#: src/views/Edit/index.js:463 +msgid "Processing & Control" +msgstr "Przetwarzanie i kontrola" + +#: src/misc/coders/Encoders/video/H264NVENC.js:92 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 +#: src/misc/coders/settings/Video.js:142 +#: src/views/Edit/Wizard/index.js:607 +msgid "Profile" +msgstr "Profil" + +#: src/views/Edit/Sources/Network.js:520 +#: src/views/Publication/Services/Akamai.js:144 +#: src/views/Publication/Services/Akamai.js:182 +#: src/views/Publication/Services/Bitmovin.js:86 +#: src/views/Publication/Services/Brightcove.js:87 +#: src/views/Publication/Services/CDN77.js:90 +#: src/views/Publication/Services/Core.js:91 +#: src/views/Publication/Services/DASH.js:186 +#: src/views/Publication/Services/DaCast.js:110 +#: src/views/Publication/Services/DaCast.js:168 +#: src/views/Publication/Services/HLS.js:175 +#: src/views/Publication/Services/Icecast.js:154 +#: src/views/Publication/Services/Image2.js:120 +#: src/views/Publication/Services/MPEGTS.js:154 +#: src/views/Publication/Services/RTMP.js:122 +#: src/views/Publication/Services/RTSP.js:144 +#: src/views/Publication/Services/Red5.js:105 +#: src/views/Publication/Services/SRT.js:158 +#: src/views/Publication/Services/UDP.js:124 +#: src/views/Publication/Services/WOWZA.js:122 +msgid "Protocol" +msgstr "Protokół" + +#: src/views/Publication/Add.js:353 +msgid "Protocols" +msgstr "Protokoły" + +#: src/views/Settings.js:1307 +msgid "Public domain/s" +msgstr "Domena(y) publiczna(e)" + +#: src/views/Publication/Edit.js:113 +#: src/views/Publication/Edit.js:123 +msgid "Publication service not found" +msgstr "Nie znaleziono usługi wydawniczej" + +#: src/views/Playersite.js:319 +msgid "Publication website settings saved" +msgstr "Tworzenie kopii zapasowej ustawień witryny publikacji" + +#: src/views/Main/Publication.js:163 +msgid "Publications" +msgstr "Publikacje" + +#: src/views/Edit/Sources/Network.js:657 +msgid "Pull Mode" +msgstr "Tryb ciągnięcia" + +#: src/views/Edit/Sources/Network.js:656 +msgid "Pull or recieve the data:" +msgstr "Pobierz lub odbierz dane:" + +#: src/misc/Progress.js:90 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 +msgid "Quality" +msgstr "Jakość" + +#: src/views/Edit/Sources/VirtualVideo.js:118 +msgid "RGB test pattern" +msgstr "Wzór testowy RGB" + +#: src/views/Settings.js:1824 +msgid "RTMP app for publishing." +msgstr "Aplikacja RTMP do publikacji." + +#: src/views/Settings.js:1765 +msgid "RTMP server" +msgstr "Serwer RTMP" + +#: src/views/Edit/Sources/Network.js:572 +#: src/views/Edit/Wizard/Sources/InternalRTMP.js:50 +msgid "RTMP server is not enabled" +msgstr "Serwer RTMP nie jest włączony" + +#: src/views/Settings.js:1811 +msgid "RTMP server listen address." +msgstr "Adres nasłuchiwania serwera RTMP." + +#: src/views/Settings.js:1837 +msgid "RTMP token for publishing and playing. The token is the value of the URL query parameter 'token.'" +msgstr "Token RTMP do publikowania i odtwarzania. Token jest wartością parametru zapytania adresu URL \"token”." + +#: src/views/Settings.js:1146 +#: src/views/Settings.js:1760 +msgid "RTMP/S" +msgstr "RTMP/S" + +#: src/views/Settings.js:1772 +msgid "RTMPS server" +msgstr "Serwer RTMPS" + +#: src/views/Edit/Sources/Network.js:405 +msgid "RTSP" +msgstr "RTSP" + +#: src/views/Edit/Sources/Raspicam.js:132 +#: src/views/Edit/Wizard/Sources/Raspicam.js:117 +msgid "Raspberry Pi camera" +msgstr "Kamera Raspberry Pi" + +#: src/misc/coders/Encoders/video/H264NVENC.js:144 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 +msgid "Rate control" +msgstr "Kontrola szybkości" + +#: src/views/Edit/Sources/VirtualVideo.js:161 +msgid "Ratio" +msgstr "Ratio" + +#: src/views/Edit/Sources/Network.js:434 +msgid "Read input at native speed" +msgstr "Odtwarzaj dane wejściowe z natywną prędkością" + +#: src/views/Edit/Sources/Network.js:658 +msgid "Receive Mode" +msgstr "Tryb odbioru" + +#: src/misc/ActionButton.js:32 +#: src/misc/ActionButton.js:53 +#: src/misc/controls/Process.js:46 +msgid "Reconnect" +msgstr "Połączyć ponownie" + +#: src/misc/controls/Process.js:53 +msgid "Reconnect delay (seconds)" +msgstr "Limit czasu ponownego połączenia (sekundy)" + +#: src/views/Main/index.js:340 +#: src/views/Publication/Process.js:68 +#: src/views/Publication/Process.js:81 +msgid "Reconnecting in {0}s" +msgstr "Połącz ponownie za {0}s" + +#: src/views/Settings.js:1999 +msgid "Reconnecting to Restreamer Core failed for the last {RETRIES} seconds." +msgstr "Ponowne połączenie z Restreamer Core nie powiodło się w ciągu ostatnich {RETRIES} sekund." + +#: src/views/Password.js:148 +msgid "Reconnecting to Restreamer Core failed." +msgstr "Nie udało się ponownie połączyć z Restreamer Core." + +#: src/views/Edit/Sources/ALSA.js:122 +#: src/views/Edit/Sources/AVFoundation.js:181 +#: src/views/Edit/Sources/V4L.js:117 +#: src/views/Edit/Wizard/Sources/AVFoundation.js:135 +#: src/views/Edit/Wizard/Sources/V4L.js:120 +msgid "Refresh" +msgstr "Odśwież" + +#: src/views/Publication/Services/Restream.js:86 +#: src/views/Publication/Services/Twitch.js:78 +#: src/views/Publication/Services/Twitter.js:150 +#: src/views/Publication/Services/Twitter.js:166 +msgid "Region" +msgstr "Region" + +#: src/views/Password.js:159 +#: src/views/Settings.js:2019 +msgid "Reload" +msgstr "Odnów" + +#: src/views/Settings.js:1637 +msgid "Remove the oldest entries if the /memfs is full" +msgstr "Usuń najstarsze wpisy, jeśli folder /memfs jest pełny" + +#: src/views/Settings.js:1784 +msgid "Requires activation" +msgstr "Wymaga aktywacji" + +#: src/views/Settings.js:1206 +#: src/views/Settings.js:2036 +#: src/views/Settings.js:2049 +#: src/views/Settings.js:2058 +msgid "Restart" +msgstr "Uruchom ponownie" + +#: src/views/Settings.js:2027 +msgid "Restart required" +msgstr "Wymagane jest ponowne uruchomienie" + +#: src/views/Password.js:136 +#: src/views/Settings.js:1987 +msgid "Restarting" +msgstr "Uruchom ponownie" + +#: src/views/Password.js:141 +#: src/views/Settings.js:1992 +msgid "Restarting Restreamer Core ..." +msgstr "Uruchom ponownie Restreamer Core ..." + +#: src/views/Settings.js:1015 +msgid "Restarting the application failed." +msgstr "Ponowne uruchomienie aplikacji nie powiodło się." + +#: src/views/Settings.js:1234 +msgid "Restreamer Service" +msgstr "Usługa Restreamer" + +#: src/views/Main/index.js:239 +msgid "Retrieving stream data ..." +msgstr "Pobieranie danych strumienia ..." + +#: src/views/Edit/Wizard/index.js:1128 +#: src/views/Invalid.js:43 +#: src/views/Settings.js:1116 +msgid "Retry" +msgstr "Spróbuj ponownie" + +#: src/views/Edit/Sources/VirtualVideo.js:155 +msgid "Rule" +msgstr "Reguła" + +#: src/misc/coders/settings/Audio.js:148 +msgid "Sampling" +msgstr "Próbowanie" + +#: src/views/Edit/Wizard/index.js:1087 +#: src/views/Edit/index.js:560 +#: src/views/Playersite.js:788 +#: src/views/Publication/Add.js:534 +#: src/views/Publication/Edit.js:571 +#: src/views/Publication/Player.js:452 +#: src/views/Settings.js:1977 +msgid "Save" +msgstr "Zapisać" + +#: src/views/Edit/Sources/VirtualVideo.js:148 +msgid "Scale" +msgstr "Skala" + +#: src/views/Settings.js:1723 +msgid "Seconds to keep files in cache." +msgstr "Sekundy na przechowywanie plików w pamięci podręcznej." + +#: src/misc/controls/Process.js:59 +msgid "Seconds until a process is restarted." +msgstr "Sekundy do ponownego uruchomienia procesu." + +#: src/misc/controls/Process.js:72 +msgid "Seconds until a staled process is terminated." +msgstr "Sekundy do zakończenia zablokowanego procesu." + +#: src/misc/controls/Snapshot.js:56 +msgid "Seconds until the snapshot/thumbnail of the video source is updated." +msgstr "Sekundy do zaktualizowania migawki/miniaturki źródła wideo." + +#: src/views/Settings.js:1473 +msgid "Security" +msgstr "Bezpieczeństwo" + +#: src/views/Publication/Services/Core.js:122 +#: src/views/Publication/Services/Livespotting.js:103 +msgid "Security token" +msgstr "Token bezpieczeństwa" + +#: src/views/Publication/Player.js:342 +msgid "Seekbar color" +msgstr "Kolor paska wyszukiwania (Seekbar)" + +#: src/misc/controls/HLS.js:62 +msgid "Segment length (seconds)" +msgstr "Długość segmentu (sekundy)" + +#: src/misc/controls/HLS.js:67 +msgid "Segment will be cut on the following keyframe after this time has passed. 2 is recommended." +msgstr "Po upływie tego opóźnienia segment zostanie wycięty w następnej klatce kluczowej. Zalecana jest wartość 2." + +#: src/views/Publication/Services/DASH.js:429 +#: src/views/Publication/Services/HLS.js:358 +msgid "Segmentation" +msgstr "Segmentacja" + +#: src/views/Edit/Sources/ALSA.js:108 +#: src/views/Edit/Sources/AVFoundation.js:172 +#: src/views/Edit/Sources/Framebuffer.js:99 +#: src/views/Edit/Sources/Raspicam.js:96 +#: src/views/Edit/Sources/V4L.js:103 +#: src/views/Edit/Wizard/Sources/AVFoundation.js:120 +#: src/views/Edit/Wizard/Sources/Raspicam.js:95 +#: src/views/Edit/Wizard/Sources/V4L.js:114 +msgid "Select a device:" +msgstr "Wybierz urządzenie:" + +#: src/views/Edit/Sources/VirtualAudio.js:84 +msgid "Select audio source:" +msgstr "Wybierz źródło dźwięku:" + +#: src/views/Edit/Sources/VirtualVideo.js:114 +msgid "Select source ..." +msgstr "Wybierz źródło ..." + +#: src/views/Edit/Sources/VirtualVideo.js:108 +msgid "Select video source:" +msgstr "Wybierz źródło wideo:" + +#: src/views/Edit/Wizard/index.js:268 +msgid "Select whether you pull the stream from a <0>network source (such as a network camera) or the <1>internal RTMP server (e.g., OBS streams to the Restreamer)." +msgstr "Wybierz, czy pobierasz strumień z <0>źródła sieciowego (np. kamery sieciowej), czy z <1>wewnętrznego serwera RTMP (np. strumienie OBS do Restreamer)." + +#: src/misc/EncodingSelect.js:196 +msgid "Select your encoding setting:" +msgstr "Wybierz ustawienia kodowania:" + +#: src/views/Playersite.js:588 +msgid "Selected" +msgstr "Wybrany" + +#: src/views/Playersite.js:395 +msgid "Selected channel" +msgstr "Wybrany kanał" + +#: src/views/Playersite.js:449 +msgid "Selection" +msgstr "Wybór" + +#: src/views/Settings.js:1190 +msgid "Send anonymous metrics (helps us for future development)" +msgstr "Wysyłaj anonimowe dane (pomaga nam w przyszłym rozwoju)" + +#: src/views/Edit/Sources/Network.js:542 +#: src/views/Edit/Sources/Network.js:589 +#: src/views/Edit/Wizard/Sources/InternalHLS.js:48 +#: src/views/Edit/Wizard/Sources/InternalRTMP.js:68 +msgid "Send stream to this address:" +msgstr "Wyślij stream na ten adres:" + +#: src/views/Publication/Services/Framebuffer.js:16 +msgid "Send video to Framebuffer" +msgstr "Wyślij wideo do Framebuffer" + +#: src/views/Publication/Services/DaCast.js:120 +msgid "Server" +msgstr "Serwer" + +#: src/Header.js:257 +#: src/views/Login.js:246 +#: src/views/Settings.js:1140 +#: src/views/Settings.js:1220 +msgid "Service" +msgstr "Usługa" + +#: src/views/Publication/Add.js:392 +#: src/views/Publication/Edit.js:406 +msgid "Service name" +msgstr "Nazwa serwisu" + +#: src/views/Settings.js:1271 +msgid "Service token for monitoring." +msgstr "Token serwisowy do monitorowania." + +#: src/Footer.js:240 +msgid "Sessions" +msgstr "Sesje" + +#: src/views/Settings.js:1402 +msgid "Sets a bandwidth limit in Mbit per second for outgoing HLS data transfer. All services, such as RTMP and outgoing processes, are included in the calculation. If the bandwidth is exceeded, HLS viewers receive the HTTP status code 509 (Bandwidth Limit Exceeded). 0 is unlimited." +msgstr "Ustawia limit przepustowości w Mbit na sekundę dla wychodzącego transferu danych HLS. Wszystkie usługi, takie jak RTMP i procesy wychodzące, są uwzględniane w kalkulacji. W przypadku przekroczenia przepustowości przeglądarki HLS otrzymują kod stanu HTTP 509 (Przekroczono limit przepustowości). 0 jest nieograniczone." + +#: src/views/Settings.js:1386 +msgid "Sets a viewer limit for HLS sessions. If the limit is exceeded, HLS viewers receive the HTTP status code 509 (Bandwidth Limit Exceeded). 0 is unlimited." +msgstr "Ustawia limit oglądania dla sesji HLS. W przypadku przekroczenia limitu przeglądarki HLS otrzymują kod stanu HTTP 509 (przekroczono limit przepustowości). Wartość 0 jest nieograniczona." + +#: src/views/Settings.js:1225 +msgid "Setting for connection to the service." +msgstr "Parametr połączenia serwisowego." + +#: src/views/Settings.js:1126 +msgid "Settings" +msgstr "Ustawienia" + +#: src/views/Settings.js:1128 +msgid "Settings (expert mode)" +msgstr "Parametry (tryb eksperta)" + +#: src/views/Settings.js:1653 +msgid "Settings for /data path. The access is protected by" +msgstr "Parametry ścieżki /data. Dostęp jest chroniony przez" + +#: src/views/Settings.js:1580 +msgid "Settings for /memfs path." +msgstr "Parametry ścieżki /memfs." + +#: src/views/Settings.js:958 +msgid "Settings saved. All changes will be applied after restarting the application." +msgstr "Ustawienia zostały zapisane. Wszystkie zmiany zostaną zastosowane po ponownym uruchomieniu aplikacji." + +#: src/views/Playersite.js:417 +msgid "Share button" +msgstr "Przycisk udostępniania" + +#: src/views/Playersite.js:431 +msgid "Shows a reference to the project." +msgstr "Wyświetla odniesienie do projektu." + +#: src/views/Login.js:332 +msgid "Sign up (free)" +msgstr "Zarejestruj się (bezpłatnie)" + +#: src/views/Edit/Sources/VirtualAudio.js:89 +msgid "Silence" +msgstr "Cisza" + +#: src/views/Edit/Wizard/index.js:898 +msgid "Silence Audio" +msgstr "Wycisz Dźwięk" + +#: src/views/Edit/Sources/VirtualAudio.js:91 +msgid "Sine" +msgstr "Sine" + +#: src/views/Playersite.js:381 +msgid "Sitename" +msgstr "Nazwa Strony" + +#: src/misc/coders/settings/Video.js:201 +msgid "Size" +msgstr "Rozmiar" + +#: src/views/Edit/index.js:482 +#: src/views/Main/index.js:372 +msgid "Snapshot" +msgstr "Snapshot" + +#: src/views/Login.js:316 +msgid "Social-login (OAuth2, 2FA)" +msgstr "Social-login (OAuth2, 2FA)" + +#: src/views/Edit/Sources/Network.js:418 +msgid "Socket timeout (microseconds)" +msgstr "Limit czasu dla gniazd (mikrosekundy)" + +#: src/views/Publication/Add.js:350 +msgid "Software" +msgstr "Oprogramowanie" + +#: src/views/Edit/Sources/VirtualAudio.js:88 +#: src/views/Edit/Sources/VirtualVideo.js:112 +msgid "Source" +msgstr "Źródło" + +#: src/misc/Progress.js:103 +msgid "Speed" +msgstr "Prędkość" + +#: src/misc/controls/Process.js:67 +msgid "Stale timeout (seconds)" +msgstr "Limit czasu (sekundy)" + +#: src/views/Publication/Player.js:322 +#: src/views/Settings.js:1505 +msgid "Statistics" +msgstr "Statystyki" + +#: src/views/Settings.js:1145 +#: src/views/Settings.js:1572 +msgid "Storage" +msgstr "Magazynowanie" + +#: src/views/Settings.js:1563 +msgid "Stores the viewer statistics to the disk." +msgstr "Przechowuje statystyki oglądających na dysku." + +#: src/views/Edit/StreamSelect.js:30 +#: src/views/Edit/StreamSelect.js:36 +#: src/views/Edit/StreamSelect.js:81 +#: src/views/Edit/Wizard/index.js:878 +msgid "Stream" +msgstr "Stream" + +#: src/views/Publication/Services/Akamai.js:156 +#: src/views/Publication/Services/CDN77.js:102 +msgid "Stream URL" +msgstr "Adres URL streamu" + +#: src/views/Publication/Services/CDN77.js:113 +#: src/views/Publication/Services/DaCast.js:153 +#: src/views/Publication/Services/Dummy.js:274 +#: src/views/Publication/Services/Instagram.js:84 +#: src/views/Publication/Services/Restream.js:116 +#: src/views/Publication/Services/Twitch.js:129 +#: src/views/Publication/Services/Twitter.js:175 +#: src/views/Publication/Services/Vimeo.js:73 +#: src/views/Publication/Services/Youtube.js:173 +msgid "Stream key" +msgstr "Klucz strumienia" + +#: src/views/Publication/Services/Brightcove.js:101 +#: src/views/Publication/Services/Core.js:113 +#: src/views/Publication/Services/Red5.js:136 +#: src/views/Publication/Services/WOWZA.js:158 +msgid "Stream name" +msgstr "Nazwa streamu" + +#: src/views/Publication/Services/Akamai.js:167 +msgid "Stream names" +msgstr "Nazwy stream" + +#: src/views/Playersite.js:425 +msgid "Support datarhei Restreamer" +msgstr "Wsparcie datarhei Restreamer" + +#: src/views/Edit/Sources/Network.js:361 +#: src/views/Edit/Wizard/Sources/Network.js:72 +msgid "Supports HTTP (HLS, DASH), RTP, RTSP, RTMP, SRT and more." +msgstr "Obsługuje HTTP (HLS, DASH), RTP, RTSP, RTMP, SRT i inne." + +#: src/Footer.js:184 +#: src/Header.js:275 +#: src/views/Settings.js:1851 +msgid "System" +msgstr "System" + +#: src/views/Playersite.js:351 +#: src/views/Playersite.js:440 +msgid "Template" +msgstr "Wygłąd" + +#: src/views/Playersite.js:462 +msgid "Template to be used for creating the publication website. The delete button removes the selection from the system." +msgstr "Szablon do wykorzystania przy tworzeniu strony internetowej publikacji. Przycisk Usuń usuwa zaznaczenie z systemu." + +#: src/views/Playersite.js:666 +msgid "Terms" +msgstr "Warunki" + +#: src/views/Edit/Sources/VirtualVideo.js:116 +msgid "Test pattern" +msgstr "Wzór testu" + +#: src/views/Edit/Sources/VirtualVideo.js:117 +msgid "Test pattern (extended)" +msgstr "Wzór testu (rozszerzony)" + +#: src/views/Playersite.js:519 +msgid "Text colors" +msgstr "Kolory tekstu" + +#: src/views/Edit/Sources/VirtualAudio.js:131 +msgid "The amplitude (0.0 - 1.0) of the generated audio stream" +msgstr "Rozległość (0,0–1,0) generowanego strumienia audio" + +#: src/views/Settings.js:1210 +msgid "The application is using an older version of the settings." +msgstr "Aplikacja korzysta ze starej wersji ustawień." + +#: src/misc/coders/settings/Audio.js:40 +msgid "The bitrate of the audio stream." +msgstr "Szybkość transmisji strumienia audio." + +#: src/views/Edit/Sources/VirtualAudio.js:150 +msgid "The carrier frequency" +msgstr "Częstotliwość nośna" + +#: src/views/Edit/index.js:352 +msgid "The channel \"{0}\" could not be deleted" +msgstr "Nie można usunąć kanału \"{0}”" + +#: src/views/Edit/index.js:361 +msgid "The channel \"{0}\" has been deleted" +msgstr "Kanał \"{0}” został usunięty" + +#: src/views/Edit/index.js:604 +msgid "The deletion of this channel can not be recovered. All publications of this channel will be removed." +msgstr "Usunięcia tego kanału nie można odzyskać. Wszystkie posty w tym kanale zostaną usunięte." + +#: src/views/Edit/Wizard/index.js:170 +#: src/views/Edit/index.js:290 +msgid "The input profile is not complete. Please define a video and audio source." +msgstr "Profil wpisu nie jest kompletny. Ustaw źródło wideo i audio." + +#: src/misc/coders/settings/Audio.js:86 +msgid "The layout of the audio stream." +msgstr "Układ strumienia audio." + +#: src/misc/controls/HLS.js:79 +msgid "The maximum number of playlist segments. 0 will contain all the segments. 6 is recommended." +msgstr "Maksymalna liczba segmentów na liście odtwarzania. 0 będzie zawierało wszystkie segmenty. 6 jest zalecane." + +#: src/views/Edit/Sources/VirtualAudio.js:119 +msgid "The noise color" +msgstr "Kolor szumu" + +#: src/misc/controls/License/index.js:60 +msgid "The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission." +msgstr "Osoba, która powiązała utwór z tym aktem, przekazała utwór do domeny publicznej, zrzekając się wszystkich praw do utworu na całym świecie zgodnie z prawem autorskim, w tym wszystkich praw pokrewnych i praw sąsiadów, w zakresie dozwolonym przez prawo. Możesz kopiować, modyfikować, rozpowszechniać i wykonywać pracę, nawet w celach komercyjnych, bez pytania o pozwolenie." + +#: src/views/Settings.js:1315 +msgid "The public reachable domain name of the host this Restreamer is running on. Separate multiple domain names by a comma." +msgstr "Publiczna nazwa domeny hosta, na którym działa ten Restreamer. Poszczególne nazwy domen oddziel przecinkami." + +#: src/views/Publication/Edit.js:270 +msgid "The publication service \"{0}\" could not be deleted" +msgstr "Nie można usunąć usługi publikowania \"{0}”." + +#: src/views/Publication/Add.js:188 +msgid "The publication service \"{0}\" has been created" +msgstr "Usługa publikowania \"{0}” została utworzona." + +#: src/views/Publication/Edit.js:276 +msgid "The publication service \"{0}\" has been deleted" +msgstr "Usługa publikowania \"{0}” została usunięta." + +#: src/views/Publication/Add.js:186 +msgid "The publication service has been created" +msgstr "Powstał serwis wydawniczy" + +#: src/misc/coders/settings/Audio.js:137 +msgid "The sample rate of the audio stream." +msgstr "Częstotliwość próbkowania strumienia audio." + +#: src/views/Playersite.js:152 +#: src/views/Playersite.js:227 +#: src/views/Publication/Player.js:189 +msgid "The selected file is too big ({0} bytes). Only {1} bytes are allowed." +msgstr "Wybrany plik jest za duży ({0} bajtów). Dozwolonych jest tylko {1} bajtów." + +#: src/views/Playersite.js:141 +#: src/views/Playersite.js:216 +#: src/views/Publication/Player.js:178 +msgid "The selected file type ({0}) is not allowed. Allowed file types are {types}" +msgstr "Wybrany typ pliku ({0}) jest niedozwolony. Dozwolone typy plików to {types}" + +#: src/views/Publication/Edit.js:230 +msgid "The settings for \"{0}\" have been saved" +msgstr "Ustawienia dla \"{0}” zostały zapisane." + +#: src/views/Edit/Wizard/index.js:846 +msgid "The source doesn't provide any audio streams." +msgstr "Źródło nie zapewnia strumienia audio." + +#: src/views/Edit/Profile.js:487 +msgid "The source doesn't provide any audio streams. Please check the <0>probe details." +msgstr "Źródło nie zapewnia strumienia audio. Sprawdź <0>szczegóły sondy." + +#: src/views/Edit/Wizard/index.js:854 +msgid "The source doesn't provide any compatible audio streams." +msgstr "Źródło nie zapewnia kompatybilnego strumienia audio." + +#: src/views/Edit/Wizard/index.js:392 +msgid "The source doesn't provide any compatible video streams. Please check the <0>requirements." +msgstr "Źródło nie zapewnia kompatybilnego strumienia wideo. Sprawdź <0>wymagania." + +#: src/views/Edit/Profile.js:357 +msgid "The source doesn't provide any video streams. Please check the <0>probe details." +msgstr "Źródło nie zapewnia strumienia wideo. Sprawdź <0>szczegóły sondy." + +#: src/views/Edit/Wizard/index.js:384 +msgid "The source doesn't provide any video streams. Please check the device." +msgstr "Źródło nie zapewnia strumienia wideo. Sprawdź urządzenie." + +#: src/views/Edit/Wizard/index.js:865 +msgid "The video source doesn't provide any compatible audio stream. <0>Silence audio is recommended. Services e.g. YouTube, Facebook & Co. require an audio channel." +msgstr "Źródło wideo nie zapewnia kompatybilnego strumienia audio. Zalecana jest <0>wyciszenie dźwięku. Usługi takie jak YouTube, Facebook i Spółka wymagają kanału audio." + +#: src/views/Edit/Wizard/index.js:603 +msgid "The video source is compatible. Select the desired resolution:" +msgstr "Źródło wideo jest kompatybilne. Wybierz żądaną rozdzielczość:" + +#: src/views/Settings.js:1182 +msgid "There are updates available. Here you get more information." +msgstr "Dostępne są aktualizacje. Tutaj uzyskasz więcej informacji." + +#: src/views/Settings.js:911 +msgid "There was a problem storing the settings. Settings not saved." +msgstr "Podczas zapisywania ustawień wystąpił problem. Ustawienia nie zostały zapisane." + +#: src/views/Invalid.js:32 +msgid "There was an error connecting to Restreamer Core at {0}." +msgstr "Wystąpił błąd podczas łączenia z Restreamer Core o {0}." + +#: src/views/Playersite.js:165 +#: src/views/Playersite.js:240 +#: src/views/Publication/Player.js:202 +msgid "There was an error during upload: {0}" +msgstr "Wystąpił błąd podczas pobierania: {0}" + +#: src/views/Edit/Wizard/index.js:1123 +msgid "There was an error setting up the stream." +msgstr "Wystąpił błąd podczas konfigurowania strumienia." + +#: src/views/Settings.js:909 +msgid "There were some errors in the settings. Settings not saved." +msgstr "Wystąpiły błędy w ustawieniach. Ustawienia nie zostały zapisane." + +#: src/views/Login.js:257 +msgid "There's no login method available." +msgstr "Nie ma dostępnej metody połączenia." + +#: src/views/Publication/Services/Dummy.js:26 +msgid "This is a dummy service that explains to you the concepts of service." +msgstr "Jest to fikcyjna usługa, która wyjaśnia Ci koncepcje usługi." + +#: src/views/Password.js:151 +msgid "This is not necessarily an error. However, it may take a bit longer for Restreamer Core to restart.." +msgstr "Niekoniecznie jest to błąd. Jednak ponowne uruchomienie Restreamer Core może potrwać nieco dłużej..." + +#: src/views/Publication/Services/Dummy.js:31 +msgid "This is to mention the copyright regulations for the target of this service." +msgstr "Ma to na celu wspomnieć o zasadach dotyczących praw autorskich dla celu tej usługi." + +#: src/misc/controls/License/index.js:95 +msgid "This license allows reusers to copy and distribute the material in any medium or format in unadapted form only, and only so long as attribution is given to the creator. The license allows for commercial use." +msgstr "Ta licencja umożliwia ponownemu użytkownikowi kopiowanie i rozpowszechnianie materiału w dowolnym medium lub formacie, wyłącznie w nieodpowiedniej formie, pod warunkiem, że twórca zostanie potwierdzony. Licencja pozwala na wykorzystanie komercyjne." + +#: src/misc/controls/License/index.js:102 +msgid "This license allows reusers to copy and distribute the material in any medium or format in unadapted form only, for noncommercial purposes only, and only so long as attribution is given to the creator." +msgstr "Niniejsza licencja umożliwia ponownemu kopiowaniu i rozpowszechnianiu materiału w dowolnym medium lub formacie, wyłącznie w nieodpowiedniej formie, do celów niekomercyjnych i pod warunkiem, że twórca zostanie potwierdzony." + +#: src/misc/controls/License/index.js:81 +msgid "This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format for noncommercial purposes only, and only so long as attribution is given to the creator." +msgstr "Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie wyłącznie do celów niekomercyjnych, pod warunkiem uznania autora za twórcę." + +#: src/misc/controls/License/index.js:88 +msgid "This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format for noncommercial purposes only, and only so long as attribution is given to the creator. If you remix, adapt, or build upon the material, you must license the modified material under identical terms." +msgstr "Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie wyłącznie do celów niekomercyjnych, pod warunkiem uznania autora za twórcę. Jeśli remiksujesz, adaptujesz lub rozszerzasz materiał, musisz licencjonować zmodyfikowany materiał na identycznych warunkach." + +#: src/misc/controls/License/index.js:67 +msgid "This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format, so long as attribution is given to the creator. The license allows for commercial use." +msgstr "Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie, pod warunkiem, że twórca zostanie potwierdzony. Licencja pozwala na wykorzystanie komercyjne." + +#: src/misc/controls/License/index.js:74 +msgid "This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or format, so long as attribution is given to the creator. The license allows for commercial use. If you remix, adapt, or build upon the material, you must license the modified material under identical terms." +msgstr "Ta licencja umożliwia ponownemu użytkownikowi rozpowszechnianie, remiksowanie, adaptowanie i używanie materiału w dowolnym medium lub formacie, pod warunkiem, że twórca zostanie potwierdzony. Licencja pozwala na wykorzystanie komercyjne. Jeśli remiksujesz, adaptujesz lub rozszerzasz materiał, musisz licencjonować zmodyfikowany materiał na identycznych warunkach." + +#: src/views/Edit/index.js:585 +msgid "This source cannot be edited while it is in use. To continue, you have to disconnect the source." +msgstr "Tego źródła nie można edytować podczas używania. Aby kontynuować, musisz odłączyć źródło." + +#: src/views/Incompatible.js:21 +msgid "This version of the UI doesn't support the available FFmpeg binary ({0}). The UI requires {1}. Please use a supported FFmpeg binary." +msgstr "Ta wersja interfejsu użytkownika nie obsługuje dostępnego pliku binarnego FFmpeg ({0}). Interfejs użytkownika wymaga {1}. Użyj obsługiwanego pliku binarnego FFmpeg." + +#: src/views/Incompatible.js:14 +msgid "This version of the UI doesn't support the connected Core ({0}). The UI requires {1}. Please use a compatible version of the UI." +msgstr "Ta wersja interfejsu użytkownika nie obsługuje podłączonego Core ({0}). Interfejs użytkownika wymaga {1}. Użyj zgodnej wersji interfejsu użytkownika." + +#: src/views/Incompatible.js:10 +msgid "This version of the UI is compatible." +msgstr "Ta wersja interfejsu użytkownika jest zgodna." + +#: src/views/Settings.js:1550 +msgid "Time until an inactive viewer connection is treated as closed." +msgstr "Czas, po którym nieaktywne połączenie widza jest traktowane jako zamknięte." + +#: src/views/Settings.js:1263 +#: src/views/Settings.js:1829 +msgid "Token" +msgstr "Token" + +#: src/views/Publication/Services/Image2.js:25 +msgid "Transmit snapshots of the main source to an HTTP/S Server. More details about the settings can be found <0>here." +msgstr "Przesyłaj migawki z podstawowego źródła do serwera HTTP/S. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Icecast.js:21 +msgid "Transmit the audio channel of the main source to an Icecast Server. More details about the settings can be found <0>here." +msgstr "Przesyła kanał audio z głównego źródła do serwera Icecast. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/HLS.js:29 +msgid "Transmit the main source as HTTP-Live-Streaming (HLS) to an HTTP/S Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło jako HTTP-Live-Streaming (HLS) do serwera HTTP/S. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/DASH.js:27 +msgid "Transmit the main source as MPEG-DASH to an HTTP/S Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło w MPEG-DASH do serwera HTTP/S. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Brightcove.js:15 +msgid "Transmit the main source to a Brightcove Live Service. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do usługi Brightcove Live. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/CDN77.js:15 +msgid "Transmit the main source to an CDN77 RTMP Service. More about the setup <0>here." +msgstr "Prześlij główne źródło do usługi CDN77 RTMP. Więcej informacji o konfiguracji <0>tutaj." + +#: src/views/Publication/Services/DaCast.js:18 +msgid "Transmit the main source to an DaCast RTMP Service. More about the setup <0>here." +msgstr "Prześlij główne źródło do usługi DaCast RTMP. Więcej informacji o konfiguracji <0>tutaj." + +#: src/views/Publication/Services/MPEGTS.js:27 +msgid "Transmit the main source to an MPEG-TS Service. More details about the settings can be found here <0>here." +msgstr "Prześlij główne źródło do usługi MPEG-TS. Więcej informacji na temat ustawień znajdziesz tutaj <0>tutaj." + +#: src/views/Publication/Services/RTMP.js:24 +msgid "Transmit the main source to an RTMP(e|s|t|te|ts) Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do serwera RTMP(e|s|t|te|ts). Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/RTSP.js:28 +msgid "Transmit the main source to an RTSP Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do serwera RTSP. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Red5.js:17 +msgid "Transmit the main source to an Red5/Pro Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do serwera Red5/Pro. Więcej szczegółów na temat ustawień znajdziesz <0>tutaj." + +#: src/views/Publication/Services/SRT.js:25 +msgid "Transmit the main source to an SRT Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do serwera SRT. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/UDP.js:23 +msgid "Transmit the main source to an UDP Server. More details about the settings can be found <0>here." +msgstr "Prześlij źródło podstawowe do serwera UDP. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/WOWZA.js:20 +msgid "Transmit the main source to an WOWZA Server. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do serwera WOWZA. Więcej szczegółów na temat ustawień znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Core.js:18 +msgid "Transmit the main source to an datarhei Core Ressource. More details about the settings can be found <0>here." +msgstr "Przekaż źródło podstawowe do datarhei Core Ressource. Więcej szczegółów na temat ustawień można znaleźć <0>tutaj." + +#: src/views/Publication/Services/Livespotting.js:15 +msgid "Transmit the main source to an livespotting.com Ressource. More details about the settings can be found <0>here." +msgstr "Przekaż główne źródło do Ressource livespotting.com. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Akamai.js:17 +msgid "Transmit the main source to the Akamai (MSL) Media Services Live. More details about the MSL Encoder settings can be found on <0>here." +msgstr "Prześlij podstawowe źródło do usługi Akamai (MSL) Media Services Live. Więcej szczegółów na temat ustawień kodera MSL można znaleźć <0>tutaj." + +#: src/views/Publication/Services/Bitmovin.js:15 +msgid "Transmit the main source to the Bitmovin cloud encoding service, a powerful tool for live streaming. More details about the settings can be founds <0>here." +msgstr "Prześlij główne źródło do usługi kodowania w chmurze Bitmovin, potężnego narzędzia do przesyłania strumieniowego na żywo. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Restream.js:18 +msgid "Transmit the main source to the Restream RTMP Service. More details about the settings can be found <0>here." +msgstr "Prześlij główne źródło do usługi Restream RTMP. Więcej szczegółów na temat parametrów znajdziesz <0>tutaj." + +#: src/views/Publication/Services/Youtube.js:21 +msgid "Transmits your video as an RTMP stream with the required key generated in YouTube Studio. You can find more information on setting up a live stream at YouTube's <0>Creator Academy." +msgstr "Przesyła Twój film jako strumień RTMP z wymaganym kluczem wygenerowanym w YouTube Studio. Więcej informacji na temat konfigurowania transmisji na żywo znajdziesz w witrynie <0>Creator Academy YouTube." + +#: src/views/Publication/Services/Twitter.js:20 +msgid "Transmits your video stream with the required key, which was generated in Twitter Producer. You can find more information on seting up a live stream at Twitter's <0>Producer." +msgstr "Przesyła strumień wideo z wymaganym kluczem, który został wygenerowany w programie Twitter Producer. Więcej informacji na temat konfigurowania transmisji na żywo można znaleźć na stronie <0>Producent Twittera." + +#: src/misc/coders/Encoders/video/X264.js:83 +#: src/misc/coders/Encoders/video/X265.js:83 +msgid "Tune" +msgstr "Tune" + +#: src/views/Edit/Sources/Network.js:409 +#: src/views/Edit/Wizard/Sources/Network.js:77 +msgid "UDP transport" +msgstr "Transport UDP" + +#: src/views/Settings.js:1111 +msgid "Unable to load the config." +msgstr "Nie udało się wczytać konfiguracji." + +#: src/views/Settings.js:1245 +msgid "Unique ident on the service." +msgstr "Unikalny identyfikator w usłudze." + +#: src/views/Main/Egress.js:91 +msgid "Unknown" +msgstr "Nieznany" + +#: src/views/Playersite.js:597 +msgid "Unselected" +msgstr "Nie zaznaczone" + +#: src/views/Playersite.js:482 +#: src/views/Playersite.js:499 +#: src/views/Playersite.js:634 +#: src/views/Publication/Player.js:373 +msgid "Upload" +msgstr "Upload" + +#: src/views/Playersite.js:281 +msgid "Uploading the file failed" +msgstr "Przesyłanie pliku nie powiodło się" + +#: src/views/Publication/Player.js:232 +msgid "Uploading the logo failed" +msgstr "Nie udało się pobrać logo" + +#: src/Footer.js:165 +#: src/misc/Progress.js:51 +#: src/views/Main/Progress.js:59 +msgid "Uptime" +msgstr "Czas operacyjny" + +#: src/views/Login.js:343 +msgid "Use Auth0 for your running Restreamer Core. More <0>details." +msgstr "Użyj Auth0 dla działającego Restreamera Core. Więcej <0>szczegółów." + +#: src/views/Edit/index.js:426 +msgid "Use the wizard (<0/>) for a quick and easy setup, or edit (<1/>) the sources directly in custom mode." +msgstr "Użyj kreatora (<0/>) do szybkiej i łatwej konfiguracji lub edytuj (<1/>) źródła bezpośrednio w trybie niestandardowym." + +#: src/views/Edit/Wizard/index.js:1068 +msgid "Use your copyright and choose the correct image license. Whether free for all or highly restricted. Briefly discuss what others are allowed to do with your image." +msgstr "Wykorzystaj swoje prawa autorskie i wybierz odpowiednią licencję na obraz. Bez względu na to, czy jest darmowy dla wszystkich, czy mocno ograniczony. Krótko omów, co inni mogą zrobić z Twoim wizerunkiem." + +#: src/views/Edit/index.js:530 +msgid "Use your copyright and choose the right image licence. Whether free for all or highly restricted. Briefly discuss what others are allowed to do with your image." +msgstr "Wykorzystaj swoje prawa autorskie i wybierz odpowiednią licencję na obraz. Niezależnie od tego, czy jest to licencja bezpłatna, czy bardzo ograniczona. Krótko omów, co inni mogą zrobić z Twoim wizerunkiem." + +#: src/views/Password.js:86 +msgid "User registration" +msgstr "Rejestracja Użytkownika" + +#: src/views/Edit/Sources/Network.js:370 +#: src/views/Edit/Wizard/Sources/Network.js:81 +#: src/views/Login.js:272 +#: src/views/Publication/Services/DASH.js:195 +#: src/views/Publication/Services/DaCast.js:131 +#: src/views/Publication/Services/HLS.js:184 +#: src/views/Publication/Services/RTSP.js:153 +#: src/views/Publication/Services/Red5.js:146 +#: src/views/Publication/Services/WOWZA.js:168 +#: src/views/Settings.js:1440 +#: src/views/Settings.js:1598 +msgid "Username" +msgstr "Login" + +#: src/views/Settings.js:1446 +#: src/views/Settings.js:1606 +msgid "Username for authorization." +msgstr "Nazwa użytkownika do autoryzacji." + +#: src/views/Edit/Sources/Network.js:375 +#: src/views/Edit/Wizard/Sources/Network.js:83 +msgid "Username for the device." +msgstr "Nazwa użytkownika urządzenia." + +#: src/views/Publication/Services/Livespotting.js:88 +msgid "VPU ID" +msgstr "VPU ID" + +#: src/views/Publication/Add.js:476 +msgid "Video" +msgstr "Wideo" + +#: src/views/Edit/Sources/AVFoundation.js:126 +#: src/views/Edit/Sources/Raspicam.js:89 +#: src/views/Edit/Sources/V4L.js:109 +#: src/views/Edit/Wizard/Sources/AVFoundation.js:82 +#: src/views/Edit/Wizard/Sources/Raspicam.js:86 +#: src/views/Edit/Wizard/Sources/V4L.js:105 +msgid "Video device" +msgstr "Urządzenie wideo" + +#: src/views/Edit/Profile.js:320 +#: src/views/Edit/ProfileSummary.js:66 +#: src/views/Publication/Edit.js:517 +msgid "Video settings" +msgstr "Ustawienia wideo" + +#: src/views/Edit/Wizard/index.js:264 +#: src/views/Edit/Wizard/index.js:354 +#: src/views/Edit/Wizard/index.js:596 +msgid "Video setup" +msgstr "Konfiguracja wideo" + +#: src/views/Edit/Sources/VideoAudio.js:45 +msgid "Video source" +msgstr "Źródło wideo" + +#: src/Footer.js:227 +#: src/Footer.js:232 +#: src/Footer.js:245 +#: src/views/Main/Publication.js:173 +msgid "Viewer" +msgstr "Widz" + +#: src/views/Edit/Sources/VirtualAudio.js:187 +#: src/views/Edit/Sources/VirtualVideo.js:206 +msgid "Virtual source" +msgstr "Wirtualne źródło" + +#: src/views/Welcome.js:27 +msgid "Welcome to Restreamer v2, the solution for fast and easy video publishing. Free for private and commercial use. Further help in the <0>docs." +msgstr "Witamy w Restreamer v2, rozwiązanie do szybkiego i łatwego publikowania filmów. Bezpłatnie do użytku prywatnego i komercyjnego. Więcej pomocy w <0>dokumentacji." + +#: src/views/Settings.js:1585 +msgid "Write protection" +msgstr "Ochrona przed zapisem" + +#: src/views/Edit/Sources/VirtualVideo.js:119 +msgid "YUV test pattern" +msgstr "Tabela testowa YUV" + +#: src/views/Edit/Wizard/index.js:1177 +msgid "Yes" +msgstr "Tak" + +#: src/views/Edit/Wizard/index.js:1159 +msgid "You can't abort the wizard because at least one input must be defined." +msgstr "Nie można przerwać kreatora, ponieważ należy zdefiniować co najmniej jeden wpis." + +#: src/views/Settings.js:2041 +msgid "You have changed the configuration. In order for the changes to take effect, you have to restart the application. Do you want to restart now?" +msgstr "Zmieniłeś konfigurację. Aby zmiany odniosły skutek, musisz ponownie uruchomić aplikację. Czy chcesz teraz ponownie uruchomić?" + +#: src/views/Main/index.js:347 +#: src/views/Publication/Process.js:73 +msgid "You have to reconnect manually" +msgstr "Musisz ponownie połączyć się ręcznie" + +#: src/views/Publication/Edit.js:456 +msgid "You have unsaved changes. Please save them before you can control the service again." +msgstr "Masz niezapisane zmiany. Utwórz ich kopię zapasową, zanim będziesz mógł ponownie kontrolować usługę." + +#: src/views/Edit/Wizard/index.js:616 +msgid "Your stream needs to be encoded, but there's no suitable encoder available." +msgstr "Twój strumień musi być zakodowany, ale nie jest dostępny odpowiedni koder." + +#: src/views/Edit/Wizard/index.js:623 +msgid "Your stream needs to be encoded. Choose the desired encoder:" +msgstr "Twój strumień musi być zakodowany. Wybierz żądany koder:" + +#: src/views/Edit/Sources/VirtualAudio.js:114 +msgid "blue" +msgstr "niebieski" + +#: src/views/Edit/Sources/VirtualAudio.js:113 +msgid "brown" +msgstr "brązowy" + +#: src/views/Publication/Player.js:331 +msgid "iframe code" +msgstr "Kod iframe" + +#: src/misc/Progress.js:77 +#: src/views/Main/Progress.js:69 +#: src/views/Main/Publication.js:184 +msgid "kbit/s" +msgstr "kbit/s" + +#: src/views/Edit/Sources/VirtualAudio.js:112 +msgid "pink" +msgstr "różowy" + +#: src/views/Edit/Sources/VirtualAudio.js:116 +msgid "velvet" +msgstr "aksamitny" + +#: src/views/Edit/Sources/VirtualAudio.js:115 +msgid "violet" +msgstr "fioletowy" + +#: src/views/Edit/Sources/VirtualAudio.js:111 +msgid "white" +msgstr "biały" diff --git a/src/locales/pt/messages.po b/src/locales/pt/messages.po index 6dbae98..5a269bd 100644 --- a/src/locales/pt/messages.po +++ b/src/locales/pt/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Processamento e controle" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Puxar ou receber os dados:" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Qualidade" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Câmera Raspberry Pi" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Controle de tarifas" diff --git a/src/locales/ru/messages.po b/src/locales/ru/messages.po index 342d11f..1af928f 100644 --- a/src/locales/ru/messages.po +++ b/src/locales/ru/messages.po @@ -1619,7 +1619,7 @@ msgid "Processing & Control" msgstr "Обработка и контроль" #: src/misc/coders/Encoders/video/H264NVENC.js:92 -#: src/misc/coders/Encoders/video/H264VAAPI.js:82 +#: src/misc/coders/Encoders/video/H264VAAPI.js:80 #: src/misc/coders/settings/Video.js:142 #: src/views/Edit/Wizard/index.js:607 msgid "Profile" @@ -1678,7 +1678,7 @@ msgid "Pull or recieve the data:" msgstr "Вытяните или получите данные:" #: src/misc/Progress.js:90 -#: src/misc/coders/Encoders/video/H264VAAPI.js:137 +#: src/misc/coders/Encoders/video/H264VAAPI.js:135 msgid "Quality" msgstr "Качество" @@ -1726,7 +1726,7 @@ msgid "Raspberry Pi camera" msgstr "Камера Raspberry Pi" #: src/misc/coders/Encoders/video/H264NVENC.js:144 -#: src/misc/coders/Encoders/video/H264VAAPI.js:63 +#: src/misc/coders/Encoders/video/H264VAAPI.js:61 msgid "Rate control" msgstr "Контроль скорости" diff --git a/src/misc/LanguageSelect.js b/src/misc/LanguageSelect.js index 2b839d2..b73cdca 100644 --- a/src/misc/LanguageSelect.js +++ b/src/misc/LanguageSelect.js @@ -44,10 +44,11 @@ export default function LanguageSelect(props) { ); diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index fe2b8b8..e6127d1 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -2753,9 +2753,9 @@ class Restreamer { async _removePublicEssentials() { await this._deleteAsset('/robots.txt'); - await this._deleteAsset('/favicon.ico', '/favicon.ico'); - await this._deleteAsset('/logo192.png', '/logo192.png'); - await this._deleteAsset('/logo512.png', '/logo512.png'); + await this._deleteAsset('/favicon.ico'); + await this._deleteAsset('/logo192.png'); + await this._deleteAsset('/logo512.png'); } async _getLocalAssetAsString(localPath) { diff --git a/src/views/Edit/ProfileSummary.js b/src/views/Edit/ProfileSummary.js index c3c916e..1dcf9f5 100644 --- a/src/views/Edit/ProfileSummary.js +++ b/src/views/Edit/ProfileSummary.js @@ -13,11 +13,11 @@ import * as M from '../../utils/metadata'; import Summary from './Summary'; function IconWizard(props) { - return (); + return ; } function IconEdit(props) { - return (); + return ; } const useStyles = makeStyles((theme) => ({ From 28c376f5a73fab5dba0078b70807fcd24bbef580 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Wed, 29 Jun 2022 21:51:10 +0200 Subject: [PATCH 06/78] Allow decoders and encoders to set global options For more details please read the src/misc/coders/README.md --- src/misc/coders/Decoders/audio/Default.js | 5 +- src/misc/coders/Decoders/video/Default.js | 5 +- src/misc/coders/Decoders/video/H264CUVID.js | 5 +- src/misc/coders/Decoders/video/H264MMAL.js | 5 +- src/misc/coders/Decoders/video/HEVCCUVID.js | 5 +- src/misc/coders/Decoders/video/MJPEGCUVID.js | 5 +- src/misc/coders/Decoders/video/MPEG1CUVID.js | 5 +- src/misc/coders/Decoders/video/MPEG2CUVID.js | 5 +- src/misc/coders/Decoders/video/MPEG2MMAL.js | 5 +- src/misc/coders/Decoders/video/MPEG4CUVID.js | 5 +- src/misc/coders/Decoders/video/MPEG4MMAL.js | 5 +- src/misc/coders/Decoders/video/NVDEC.js | 5 +- src/misc/coders/Decoders/video/VC1CUVID.js | 5 +- src/misc/coders/Decoders/video/VC1MMAL.js | 5 +- src/misc/coders/Decoders/video/VP8CUVID.js | 5 +- src/misc/coders/Decoders/video/VP9CUVID.js | 5 +- .../coders/Decoders/video/VideoToolbox.js | 5 +- src/misc/coders/Encoders/audio/AAC.js | 9 +- .../coders/Encoders/audio/AACAudioToolbox.js | 9 +- src/misc/coders/Encoders/audio/Copy.js | 10 +- src/misc/coders/Encoders/audio/Libopus.js | 7 +- src/misc/coders/Encoders/audio/Libvorbis.js | 7 +- src/misc/coders/Encoders/audio/MP3.js | 7 +- src/misc/coders/Encoders/audio/None.js | 7 +- src/misc/coders/Encoders/audio/Opus.js | 9 +- src/misc/coders/Encoders/audio/Vorbis.js | 7 +- src/misc/coders/Encoders/video/Copy.js | 7 +- src/misc/coders/Encoders/video/H264NVENC.js | 15 +- src/misc/coders/Encoders/video/H264OMX.js | 11 +- src/misc/coders/Encoders/video/H264V4L2M2M.js | 11 +- src/misc/coders/Encoders/video/H264VAAPI.js | 11 +- .../coders/Encoders/video/H264VideoToolbox.js | 13 +- src/misc/coders/Encoders/video/None.js | 7 +- src/misc/coders/Encoders/video/Raw.js | 7 +- src/misc/coders/Encoders/video/VP9.js | 9 +- src/misc/coders/Encoders/video/X264.js | 13 +- src/misc/coders/Encoders/video/X265.js | 13 +- src/misc/coders/README.md | 118 +++++++++++++ src/utils/metadata.js | 162 +++++++++++++----- src/utils/restreamer.js | 12 +- src/views/Edit/Wizard/index.js | 4 +- src/views/Edit/index.js | 4 +- src/views/Publication/Add.js | 58 ++----- src/views/Publication/Edit.js | 58 ++----- src/views/Publication/helper.js | 4 +- 45 files changed, 493 insertions(+), 201 deletions(-) create mode 100644 src/misc/coders/README.md diff --git a/src/misc/coders/Decoders/audio/Default.js b/src/misc/coders/Decoders/audio/Default.js index f9db3b7..a1d3cac 100644 --- a/src/misc/coders/Decoders/audio/Default.js +++ b/src/misc/coders/Decoders/audio/Default.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = []; + const mapping = { + global: [], + local: [], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/Default.js b/src/misc/coders/Decoders/video/Default.js index be7cc80..1dc1411 100644 --- a/src/misc/coders/Decoders/video/Default.js +++ b/src/misc/coders/Decoders/video/Default.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = []; + const mapping = { + global: [], + local: [], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/H264CUVID.js b/src/misc/coders/Decoders/video/H264CUVID.js index 887f48d..051fe18 100644 --- a/src/misc/coders/Decoders/video/H264CUVID.js +++ b/src/misc/coders/Decoders/video/H264CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'h264_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'h264_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/H264MMAL.js b/src/misc/coders/Decoders/video/H264MMAL.js index ec7a609..80feb94 100644 --- a/src/misc/coders/Decoders/video/H264MMAL.js +++ b/src/misc/coders/Decoders/video/H264MMAL.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'h264_mmal']; + const mapping = { + global: [], + local: ['-c:v', 'h264_mmal'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/HEVCCUVID.js b/src/misc/coders/Decoders/video/HEVCCUVID.js index 6731fb7..869f26a 100644 --- a/src/misc/coders/Decoders/video/HEVCCUVID.js +++ b/src/misc/coders/Decoders/video/HEVCCUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'hevc_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'hevc_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/MJPEGCUVID.js b/src/misc/coders/Decoders/video/MJPEGCUVID.js index ee6827a..fc8706a 100644 --- a/src/misc/coders/Decoders/video/MJPEGCUVID.js +++ b/src/misc/coders/Decoders/video/MJPEGCUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'mjpeg_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'mjpeg_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/MPEG1CUVID.js b/src/misc/coders/Decoders/video/MPEG1CUVID.js index 0395336..cb2ecdf 100644 --- a/src/misc/coders/Decoders/video/MPEG1CUVID.js +++ b/src/misc/coders/Decoders/video/MPEG1CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'mpeg1_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'mpeg1_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/MPEG2CUVID.js b/src/misc/coders/Decoders/video/MPEG2CUVID.js index 9f1ee68..2d88baa 100644 --- a/src/misc/coders/Decoders/video/MPEG2CUVID.js +++ b/src/misc/coders/Decoders/video/MPEG2CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'mpeg2_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'mpeg2_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/MPEG2MMAL.js b/src/misc/coders/Decoders/video/MPEG2MMAL.js index 0c7f2c8..d2166c3 100644 --- a/src/misc/coders/Decoders/video/MPEG2MMAL.js +++ b/src/misc/coders/Decoders/video/MPEG2MMAL.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'mpeg2_mmal']; + const mapping = { + global: [], + local: ['-c:v', 'mpeg2_mmal'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/MPEG4CUVID.js b/src/misc/coders/Decoders/video/MPEG4CUVID.js index 065438f..b3da8b5 100644 --- a/src/misc/coders/Decoders/video/MPEG4CUVID.js +++ b/src/misc/coders/Decoders/video/MPEG4CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'mpeg4_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'mpeg4_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/MPEG4MMAL.js b/src/misc/coders/Decoders/video/MPEG4MMAL.js index 6473f53..3e23ae4 100644 --- a/src/misc/coders/Decoders/video/MPEG4MMAL.js +++ b/src/misc/coders/Decoders/video/MPEG4MMAL.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'mpeg4_mmal']; + const mapping = { + global: [], + local: ['-c:v', 'mpeg4_mmal'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/NVDEC.js b/src/misc/coders/Decoders/video/NVDEC.js index 9194718..28b3216 100644 --- a/src/misc/coders/Decoders/video/NVDEC.js +++ b/src/misc/coders/Decoders/video/NVDEC.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-hwaccel', 'cuda']; + const mapping = { + global: [], + local: ['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/VC1CUVID.js b/src/misc/coders/Decoders/video/VC1CUVID.js index 12e50e3..b7da391 100644 --- a/src/misc/coders/Decoders/video/VC1CUVID.js +++ b/src/misc/coders/Decoders/video/VC1CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'vc1_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'vc1_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/VC1MMAL.js b/src/misc/coders/Decoders/video/VC1MMAL.js index 83cf83e..0c3fbad 100644 --- a/src/misc/coders/Decoders/video/VC1MMAL.js +++ b/src/misc/coders/Decoders/video/VC1MMAL.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'vc1_mmal']; + const mapping = { + global: [], + local: ['-c:v', 'vc1_mmal'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/VP8CUVID.js b/src/misc/coders/Decoders/video/VP8CUVID.js index 341ea3d..d298e8a 100644 --- a/src/misc/coders/Decoders/video/VP8CUVID.js +++ b/src/misc/coders/Decoders/video/VP8CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'vp8_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'vp8_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/VP9CUVID.js b/src/misc/coders/Decoders/video/VP9CUVID.js index f474ddd..5c8a409 100644 --- a/src/misc/coders/Decoders/video/VP9CUVID.js +++ b/src/misc/coders/Decoders/video/VP9CUVID.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-c:v', 'vp9_cuvid']; + const mapping = { + global: [], + local: ['-c:v', 'vp9_cuvid'], + }; return mapping; } diff --git a/src/misc/coders/Decoders/video/VideoToolbox.js b/src/misc/coders/Decoders/video/VideoToolbox.js index 760e6c8..1f77c30 100644 --- a/src/misc/coders/Decoders/video/VideoToolbox.js +++ b/src/misc/coders/Decoders/video/VideoToolbox.js @@ -9,7 +9,10 @@ function init(initialState) { } function createMapping(settings) { - const mapping = ['-hwaccel', 'videotoolbox']; + const mapping = { + global: [], + local: ['-hwaccel', 'videotoolbox'], + }; return mapping; } diff --git a/src/misc/coders/Encoders/audio/AAC.js b/src/misc/coders/Encoders/audio/AAC.js index 78e930a..a3eea58 100644 --- a/src/misc/coders/Encoders/audio/AAC.js +++ b/src/misc/coders/Encoders/audio/AAC.js @@ -28,12 +28,17 @@ function createMapping(settings, stream) { layout = stream.layout; } - const mapping = ['-codec:a', 'aac', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'aac', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; if (stream.codec === 'aac') { - mapping.push('-bsf:a', 'aac_adtstoasc'); + local.push('-bsf:a', 'aac_adtstoasc'); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/audio/AACAudioToolbox.js b/src/misc/coders/Encoders/audio/AACAudioToolbox.js index 0c47edb..f8e0525 100644 --- a/src/misc/coders/Encoders/audio/AACAudioToolbox.js +++ b/src/misc/coders/Encoders/audio/AACAudioToolbox.js @@ -28,12 +28,17 @@ function createMapping(settings, stream) { layout = stream.layout; } - const mapping = ['-codec:a', 'aac_at', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'aac_at', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; if (stream.codec === 'aac') { - mapping.push('-bsf:a', 'aac_adtstoasc'); + local.push('-bsf:a', 'aac_adtstoasc'); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/audio/Copy.js b/src/misc/coders/Encoders/audio/Copy.js index 533ed9a..d6f90cf 100644 --- a/src/misc/coders/Encoders/audio/Copy.js +++ b/src/misc/coders/Encoders/audio/Copy.js @@ -1,12 +1,18 @@ import React from 'react'; function createMapping(settings, stream) { - const mapping = ['-codec:a', 'copy']; + const local = ['-codec:a', 'copy']; /* if(stream.codec === 'aac') { - mapping.push('-bsf:a', 'aac_adtstoasc'); + local.push('-bsf:a', 'aac_adtstoasc'); } */ + + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/audio/Libopus.js b/src/misc/coders/Encoders/audio/Libopus.js index f118f9a..bb6d9d9 100644 --- a/src/misc/coders/Encoders/audio/Libopus.js +++ b/src/misc/coders/Encoders/audio/Libopus.js @@ -28,7 +28,12 @@ function createMapping(settings, stream) { layout = stream.layout; } - const mapping = ['-codec:a', 'libopus', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'libopus', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/audio/Libvorbis.js b/src/misc/coders/Encoders/audio/Libvorbis.js index 253875a..4ceafbc 100644 --- a/src/misc/coders/Encoders/audio/Libvorbis.js +++ b/src/misc/coders/Encoders/audio/Libvorbis.js @@ -28,7 +28,12 @@ function createMapping(settings, stream) { layout = stream.layout; } - const mapping = ['-codec:a', 'libvorbis', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'libvorbis', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/audio/MP3.js b/src/misc/coders/Encoders/audio/MP3.js index ed793b8..7a394c7 100644 --- a/src/misc/coders/Encoders/audio/MP3.js +++ b/src/misc/coders/Encoders/audio/MP3.js @@ -29,7 +29,12 @@ function createMapping(settings, stream) { } // '-qscale:a', '6' - const mapping = ['-codec:a', 'libmp3lame', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'libmp3lame', '-b:a', `${settings.bitrate}k`, '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/audio/None.js b/src/misc/coders/Encoders/audio/None.js index f8b7aa0..5f5c3fd 100644 --- a/src/misc/coders/Encoders/audio/None.js +++ b/src/misc/coders/Encoders/audio/None.js @@ -1,7 +1,12 @@ import React from 'react'; function createMapping(settings, stream) { - const mapping = ['-an']; + const local = ['-an']; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/audio/Opus.js b/src/misc/coders/Encoders/audio/Opus.js index 47ab8bf..17f62ed 100644 --- a/src/misc/coders/Encoders/audio/Opus.js +++ b/src/misc/coders/Encoders/audio/Opus.js @@ -34,12 +34,17 @@ function createMapping(settings, stream) { layout = stream.layout; } - const mapping = ['-codec:a', 'opus', '-b:a', `${settings.bitrate}k`, '-vbr', 'on', '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'opus', '-b:a', `${settings.bitrate}k`, '-vbr', 'on', '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; if (settings.delay !== 'auto') { - mapping.push('opus_delay', settings.delay); + local.push('opus_delay', settings.delay); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/audio/Vorbis.js b/src/misc/coders/Encoders/audio/Vorbis.js index d63e9bd..c484720 100644 --- a/src/misc/coders/Encoders/audio/Vorbis.js +++ b/src/misc/coders/Encoders/audio/Vorbis.js @@ -28,7 +28,12 @@ function createMapping(settings, stream) { layout = stream.layout; } - const mapping = ['-codec:a', 'vorbis', '-b:a', `${settings.bitrate}k`, '-qscale:a', '3', '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + const local = ['-codec:a', 'vorbis', '-b:a', `${settings.bitrate}k`, '-qscale:a', '3', '-shortest', '-af', `aresample=osr=${sampling}:ocl=${layout}`]; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/video/Copy.js b/src/misc/coders/Encoders/video/Copy.js index 95ebaaa..a162fa8 100644 --- a/src/misc/coders/Encoders/video/Copy.js +++ b/src/misc/coders/Encoders/video/Copy.js @@ -1,7 +1,12 @@ import React from 'react'; function createMapping(settings) { - const mapping = ['-codec:v', 'copy', '-vsync', '0', '-copyts', '-start_at_zero']; + const local = ['-codec:v', 'copy', '-vsync', 'passthrough', '-copyts', '-start_at_zero']; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/video/H264NVENC.js b/src/misc/coders/Encoders/video/H264NVENC.js index 5869602..5ccfb2e 100644 --- a/src/misc/coders/Encoders/video/H264NVENC.js +++ b/src/misc/coders/Encoders/video/H264NVENC.js @@ -24,7 +24,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'h264_nvenc', '-preset:v', @@ -44,21 +44,26 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } if (settings.profile !== 'auto') { - mapping.push('-profile:v', `${settings.profile}`); + local.push('-profile:v', `${settings.profile}`); } if (settings.level !== 'auto') { - mapping.push('-level:v', `${settings.level}`); + local.push('-level:v', `${settings.level}`); } if (settings.rc !== 'auto') { - mapping.push('-rc:v', `${settings.rc}`); + local.push('-rc:v', `${settings.rc}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/H264OMX.js b/src/misc/coders/Encoders/video/H264OMX.js index a0c0c0d..1aa08fc 100644 --- a/src/misc/coders/Encoders/video/H264OMX.js +++ b/src/misc/coders/Encoders/video/H264OMX.js @@ -17,7 +17,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'h264_omx', '-b:v', @@ -37,13 +37,18 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } if (settings.profile !== 'auto') { - mapping.push('-profile:v', `${settings.profile}`); + local.push('-profile:v', `${settings.profile}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/H264V4L2M2M.js b/src/misc/coders/Encoders/video/H264V4L2M2M.js index 3868367..5604c54 100644 --- a/src/misc/coders/Encoders/video/H264V4L2M2M.js +++ b/src/misc/coders/Encoders/video/H264V4L2M2M.js @@ -65,7 +65,7 @@ Codec Controls */ function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'h264_v4l2m2m', '-b:v', @@ -83,13 +83,18 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } if (settings.profile !== 'auto') { - mapping.push('-profile:v', `${settings.profile}`); + local.push('-profile:v', `${settings.profile}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/H264VAAPI.js b/src/misc/coders/Encoders/video/H264VAAPI.js index 4ba01c7..7014ade 100644 --- a/src/misc/coders/Encoders/video/H264VAAPI.js +++ b/src/misc/coders/Encoders/video/H264VAAPI.js @@ -24,7 +24,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-vaapi_device', '/dev/dri/renderD128', '-vf', @@ -46,13 +46,18 @@ function createMapping(settings) { '-g', `${settings.gop}`, '-vsync', - '1', + 'cfr', ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/H264VideoToolbox.js b/src/misc/coders/Encoders/video/H264VideoToolbox.js index 6d68d00..2ed00a0 100644 --- a/src/misc/coders/Encoders/video/H264VideoToolbox.js +++ b/src/misc/coders/Encoders/video/H264VideoToolbox.js @@ -22,7 +22,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'h264_videotoolbox', '-b:v', @@ -42,17 +42,22 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } if (settings.profile !== 'auto') { - mapping.push('-profile:v', `${settings.profile}`); + local.push('-profile:v', `${settings.profile}`); } if (settings.entropy !== 'default') { - mapping.push('-coder:v', `${settings.entropy}`); + local.push('-coder:v', `${settings.entropy}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/None.js b/src/misc/coders/Encoders/video/None.js index 6738f1b..6cd3632 100644 --- a/src/misc/coders/Encoders/video/None.js +++ b/src/misc/coders/Encoders/video/None.js @@ -1,7 +1,12 @@ import React from 'react'; function createMapping(settings, stream) { - const mapping = ['-vn']; + const local = ['-vn']; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/video/Raw.js b/src/misc/coders/Encoders/video/Raw.js index 61629aa..5c72db2 100644 --- a/src/misc/coders/Encoders/video/Raw.js +++ b/src/misc/coders/Encoders/video/Raw.js @@ -1,7 +1,12 @@ import React from 'react'; function createMapping(settings) { - const mapping = ['-codec:v', 'rawvideo']; + const local = ['-codec:v', 'rawvideo']; + + const mapping = { + global: [], + local: local, + }; return mapping; } diff --git a/src/misc/coders/Encoders/video/VP9.js b/src/misc/coders/Encoders/video/VP9.js index caa5696..0a2e4e9 100644 --- a/src/misc/coders/Encoders/video/VP9.js +++ b/src/misc/coders/Encoders/video/VP9.js @@ -16,7 +16,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'libvpx-vp9', '-b:v', @@ -34,9 +34,14 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/X264.js b/src/misc/coders/Encoders/video/X264.js index 6eaea11..ad3bbd5 100644 --- a/src/misc/coders/Encoders/video/X264.js +++ b/src/misc/coders/Encoders/video/X264.js @@ -23,7 +23,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'libx264', '-preset:v', @@ -43,17 +43,22 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } if (settings.profile !== 'auto') { - mapping.push('-profile:v', `${settings.profile}`); + local.push('-profile:v', `${settings.profile}`); } if (settings.tune !== 'none') { - mapping.push('-tune:v', `${settings.tune}`); + local.push('-tune:v', `${settings.tune}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/Encoders/video/X265.js b/src/misc/coders/Encoders/video/X265.js index ce055c2..019cc6e 100644 --- a/src/misc/coders/Encoders/video/X265.js +++ b/src/misc/coders/Encoders/video/X265.js @@ -23,7 +23,7 @@ function init(initialState) { } function createMapping(settings) { - const mapping = [ + const local = [ '-codec:v', 'libx265', '-preset:v', @@ -43,17 +43,22 @@ function createMapping(settings) { ]; if (settings.gop !== 'auto') { - mapping.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); } if (settings.profile !== 'auto') { - mapping.push('-profile:v', `${settings.profile}`); + local.push('-profile:v', `${settings.profile}`); } if (settings.tune !== 'none') { - mapping.push('-tune:v', `${settings.tune}`); + local.push('-tune:v', `${settings.tune}`); } + const mapping = { + global: [], + local: local, + }; + return mapping; } diff --git a/src/misc/coders/README.md b/src/misc/coders/README.md new file mode 100644 index 0000000..8ef022b --- /dev/null +++ b/src/misc/coders/README.md @@ -0,0 +1,118 @@ +# Decoders and Encoders + +Implementations of various decoders and encoder for audio and video. + +## Decoders + +Each decoder exports the same variables: + +``` +export { coder, name, codecs, type, hwaccel, defaults, Coder as component }; +``` + +| Variable | Description | +| -------- | -------------------------------------------------------------------- | +| coder | Name of the decoder in FFmpeg, e.g. `cuda`, `vc1_mmal`. | +| name | Name for the decoder as it will be displayed in the UI. | +| codecs | Array of codecs this coder supports, e.g. `['h264', 'h265']`. | +| type | Either `video` or `audio`. | +| hwaccel | Whether this codec uses hardware acceleration. | +| defaults | A function that returns the default settings and mapping. See below. | +| Coder | The React component. | + +### defaults + +The `defaults()` function returns the default settings and mappings for this decoder. It is an object of this shape: + +``` +{ + settings: {}, + mapping: { + global: [], + local: [], + }, +} +``` + +The `settings` is an object private to a coder and contains its settings as required for rendering the component +with options for this coder. The `mapping` object contains the FFmpeg command line options according to the settings. +It has a `global` array which contains all global options for this coder. _Each option (with its value) has to be +an array of its own_. The `local` array is an array of options for that input, e.g. + +``` +{ + settings: { + ... + }, + mapping: { + global: [ + ['-init_hw_device', 'vaapi=foo:/dev/dri/renderD128'], + ], + local: [ + '-hwaccel', 'vaapi', + '-hwaccel_output_format', 'vaapi', + '-hwaccel_device', 'foo', + ], + }, +} +``` + +Check out the existing decoders as examples for an implementation. + +## Encoders + +Each encoder exports the same variables: + +``` +export { coder, name, codec, type, hwaccel, summarize, defaults, Coder as component }; +``` + +| Variable | Description | +| --------- | ---------------------------------------------------------------------- | +| coder | Name of the encoder in FFmpeg, e.g. `libx264`. | +| name | Name for the encoder as it will be displayed in the UI. | +| codec | Name of the codec, e.g. `h264`. | +| type | Either `video` or `audio`. | +| hwaccel | Whether this codec uses hardware acceleration. | +| summarize | A function that returns a string that summarizes the current settings. | +| defaults | A function that returns the default settings and mapping. See below. | +| Coder | The React component. | + +### defaults + +The `defaults()` function returns the default settings and mappings for this encoder. It is an object of this shape: + +``` +{ + settings: {}, + mapping: { + global: [], + local: [], + }, +} +``` + +The `settings` is an object private to a coder and contains its settings as required for rendering the component +with options for this coder. The `mapping` object contains the FFmpeg command line options according to the settings. +It has a `global` array which contains all global options for this coder. _Each option (with its value) has to be +an array of its own_. The `local` array is an array of options for that input, e.g. + +``` +{ + settings: { + ... + }, + mapping: { + global: [ + ['-init_hw_device', 'vaapi=foo:/dev/dri/renderD128'], + ], + local: [ + '-filter_hw_device', 'foo', + '-filter:v', 'format=nv12|vaapi,hwupload', + '-codec:v', 'h264_vaapi', + ], + }, +} +``` + +Check out the existing encoders as examples for an implementation. diff --git a/src/utils/metadata.js b/src/utils/metadata.js index 4a93366..d8b1154 100644 --- a/src/utils/metadata.js +++ b/src/utils/metadata.js @@ -93,13 +93,16 @@ data = { channels: '2', sampling: '44100' }, - mapping: [ - '-codec:a', 'aac', - '-b:a', '64k', - '-bsf:a', 'aac_adtstoasc', - '-shortest', - '-af', 'aresample=osr=44100:ocl=2' - ] + mapping: { + global: [], + local: [ + '-codec:a', 'aac', + '-b:a', '64k', + '-bsf:a', 'aac_adtstoasc', + '-shortest', + '-af', 'aresample=osr=44100:ocl=2' + ] + } }, decoder: null, }, @@ -110,12 +113,15 @@ data = { coder: 'copy', codec: 'h264', settings: {}, - mapping: [ - '-codec:v', 'copy', - '-vsync 0', - '-copyts', - '-start_at_zero', - ] + mapping: { + global: [], + local: [ + '-codec:v', 'copy', + '-vsync 0', + '-copyts', + '-start_at_zero', + ] + } }, decoder: null, }, @@ -133,19 +139,22 @@ data = { profile: 'auto', tune: 'zerolatency', }, - mapping: [ - '-codec:v', 'libx264', - '-preset:v', 'ultrafast', - '-b:v', '4096k', - '-maxrate', '4096k', - '-bufsize', '4096k', - '-r', '25', - '-g', '50', - '-pix_fmt', 'yuv420p', - '-vsync', '1', - '-profile:v', 'high', - '-tune:v', 'zerolatency', - ] + mapping: { + global: [], + local: [ + '-codec:v', 'libx264', + '-preset:v', 'ultrafast', + '-b:v', '4096k', + '-maxrate', '4096k', + '-bufsize', '4096k', + '-r', '25', + '-g', '50', + '-pix_fmt', 'yuv420p', + '-vsync', '1', + '-profile:v', 'high', + '-tune:v', 'zerolatency', + ] + } }, decoder: { coder: 'h264_cuvid', @@ -483,11 +492,7 @@ const mergeEgressMetadata = (metadata, base) => { const validateProfile = (sources, profile) => { let validVideo = false; - if (!('video' in profile)) { - profile.video = initProfile({}); - } else { - profile.video = initProfile(profile.video); - } + profile = initProfile(profile); if (profile.video.source !== -1 && profile.video.source < sources.length) { const source = sources[profile.video.source]; @@ -505,12 +510,6 @@ const validateProfile = (sources, profile) => { let validAudio = false; - if (!('audio' in profile)) { - profile.audio = initProfile({}); - } else { - profile.audio = initProfile(profile.audio); - } - if (profile.audio.source !== -1 && profile.audio.source < sources.length) { const source = sources[profile.audio.source]; @@ -547,6 +546,7 @@ const validateProfile = (sources, profile) => { const createInputsOutputs = (sources, profiles) => { const source2inputMap = new Map(); + let global = []; const inputs = []; const outputs = []; @@ -559,11 +559,13 @@ const createInputsOutputs = (sources, profiles) => { let index = -1; + global = [...global, ...profile.video.decoder.mapping.global]; + const source = sources[profile.video.source]; const stream = source.streams[profile.video.stream]; const input = source.inputs[stream.index]; - input.options = [...profile.video.decoder.mapping, ...input.options]; + input.options = [...profile.video.decoder.mapping.local, ...input.options]; const id = profile.video.source + ':' + stream.index; @@ -576,14 +578,18 @@ const createInputsOutputs = (sources, profiles) => { index = source2inputMap.get(id); - const options = ['-map', index + ':' + stream.stream, ...profile.video.encoder.mapping]; + global = [...global, ...profile.video.encoder.mapping.global]; + + const options = ['-map', index + ':' + stream.stream, ...profile.video.encoder.mapping.local]; if (profile.audio.encoder.coder !== 'none' && profile.audio.source !== -1 && profile.audio.stream !== -1) { + global = [...global, ...profile.audio.decoder.mapping.global]; + const source = sources[profile.audio.source]; const stream = source.streams[profile.audio.stream]; const input = source.inputs[stream.index]; - input.options = [...profile.audio.decoder.mapping, ...input.options]; + input.options = [...profile.audio.decoder.mapping.local, ...input.options]; const id = profile.audio.source + ':' + stream.index; @@ -594,7 +600,9 @@ const createInputsOutputs = (sources, profiles) => { index = source2inputMap.get(id); - options.push('-map', index + ':' + stream.stream, ...profile.audio.encoder.mapping); + global = [...global, ...profile.audio.encoder.mapping.global]; + + options.push('-map', index + ':' + stream.stream, ...profile.audio.encoder.mapping.local); } else { options.push('-an'); } @@ -605,7 +613,16 @@ const createInputsOutputs = (sources, profiles) => { }); } - return [inputs, outputs]; + // https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array + const uniqBy = (a, key) => { + return [...new Map(a.map((x) => [key(x), x])).values()]; + }; + + // global is an array of arrays. Here we remove duplicates and flatten it. + global = uniqBy(global, (x) => JSON.stringify(x.sort())); + global = global.reduce((acc, val) => acc.concat(val), []); + + return [global, inputs, outputs]; }; const createOutputStreams = (sources, profiles) => { @@ -717,17 +734,44 @@ const initProfile = (initialProfile) => { profile.video.encoder = { coder: 'none', settings: {}, - mapping: [], + mapping: {}, ...profile.video.encoder, }; + // mapping used to be an array for input/output specific options + if (Array.isArray(profile.video.encoder.mapping)) { + profile.video.encoder.mapping = { + global: [], + local: profile.video.encoder.mapping, + }; + } else { + profile.video.encoder.mapping = { + global: [], + local: [], + ...profile.video.encoder.mapping, + }; + } + profile.video.decoder = { coder: 'default', settings: {}, - mapping: [], + mapping: {}, ...profile.video.decoder, }; + if (Array.isArray(profile.video.decoder.mapping)) { + profile.video.decoder.mapping = { + global: [], + local: profile.video.decoder.mapping, + }; + } else { + profile.video.decoder.mapping = { + global: [], + local: [], + ...profile.video.decoder.mapping, + }; + } + profile.audio = { source: -1, stream: -1, @@ -739,17 +783,43 @@ const initProfile = (initialProfile) => { profile.audio.encoder = { coder: 'none', settings: {}, - mapping: [], + mapping: {}, ...profile.audio.encoder, }; + if (Array.isArray(profile.audio.encoder.mapping)) { + profile.audio.encoder.mapping = { + global: [], + local: profile.audio.encoder.mapping, + }; + } else { + profile.audio.encoder.mapping = { + global: [], + local: [], + ...profile.audio.encoder.mapping, + }; + } + profile.audio.decoder = { coder: 'default', settings: {}, - mapping: [], + mapping: {}, ...profile.audio.decoder, }; + if (Array.isArray(profile.audio.decoder.mapping)) { + profile.audio.decoder.mapping = { + global: [], + local: profile.audio.decoder.mapping, + }; + } else { + profile.audio.decoder.mapping = { + global: [], + local: [], + ...profile.audio.decoder.mapping, + }; + } + profile.custom = { selected: profile.audio.source === 1, stream: profile.audio.source === 1 ? -2 : profile.audio.stream, diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index e6127d1..390ac8f 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -1427,7 +1427,7 @@ class Restreamer { } // Upsert the ingest process - async UpsertIngest(channelid, inputs, outputs, control) { + async UpsertIngest(channelid, global, inputs, outputs, control) { const channel = this.GetChannel(channelid); if (channel === null) { return [null, { message: 'Unknown channel ID' }]; @@ -1439,7 +1439,7 @@ class Restreamer { reference: channel.channelid, input: [], output: [], - options: ['-err_detect', 'ignore_err'], + options: ['-err_detect', 'ignore_err', ...global], autostart: control.process.autostart, reconnect: control.process.reconnect, reconnect_delay_seconds: parseInt(control.process.delay), @@ -2195,7 +2195,7 @@ class Restreamer { } // Update an egress process - async UpdateEgress(channelid, id, inputs, outputs, control) { + async UpdateEgress(channelid, id, global, inputs, outputs, control) { const channel = this.GetChannel(channelid); if (channel === null) { return null; @@ -2226,7 +2226,7 @@ class Restreamer { }, ], output: [], - options: ['-err_detect', 'ignore_err'], + options: ['-err_detect', 'ignore_err', ...global], autostart: control.process.autostart, reconnect: control.process.reconnect, reconnect_delay_seconds: parseInt(control.process.delay), @@ -2252,7 +2252,7 @@ class Restreamer { } // Create an egress process - async CreateEgress(channelid, service, inputs, outputs, control) { + async CreateEgress(channelid, service, global, inputs, outputs, control) { const channel = this.GetChannel(channelid); if (channel === null) { return ['', { message: 'Unknown channel ID' }]; @@ -2269,7 +2269,7 @@ class Restreamer { this.SetChannelEgress(channelid, egress.id, egress); - const [, err] = await this.UpdateEgress(channelid, egress.id, inputs, outputs, control); + const [, err] = await this.UpdateEgress(channelid, egress.id, global, inputs, outputs, control); if (err !== null) { this.DeleteChannelEgress(channelid, egress.id); } diff --git a/src/views/Edit/Wizard/index.js b/src/views/Edit/Wizard/index.js index 76563fd..1cd580b 100644 --- a/src/views/Edit/Wizard/index.js +++ b/src/views/Edit/Wizard/index.js @@ -164,7 +164,7 @@ export default function Wizard(props) { const profiles = data.profiles; const control = data.control; - const [inputs, outputs] = M.createInputsOutputs(sources, profiles); + const [global, inputs, outputs] = M.createInputsOutputs(sources, profiles); if (inputs.length === 0 || outputs.length === 0) { notify.Dispatch('error', 'save:ingest', i18n._(t`The input profile is not complete. Please define a video and audio source.`)); @@ -173,7 +173,7 @@ export default function Wizard(props) { data.streams = M.createOutputStreams(sources, profiles); - const [, err] = await props.restreamer.UpsertIngest(_channelid, inputs, outputs, control); + const [, err] = await props.restreamer.UpsertIngest(_channelid, global, inputs, outputs, control); if (err !== null) { notify.Dispatch('error', 'save:ingest', err.message); return false; diff --git a/src/views/Edit/index.js b/src/views/Edit/index.js index a390cd2..430a3c0 100644 --- a/src/views/Edit/index.js +++ b/src/views/Edit/index.js @@ -284,7 +284,7 @@ export default function Edit(props) { const profiles = $data.profiles; const control = $data.control; - const [inputs, outputs] = M.createInputsOutputs(sources, profiles); + const [global, inputs, outputs] = M.createInputsOutputs(sources, profiles); if (inputs.length === 0 || outputs.length === 0) { notify.Dispatch('error', 'save:ingest', i18n._(t`The input profile is not complete. Please define a video and audio source.`)); @@ -292,7 +292,7 @@ export default function Edit(props) { } // Create/update the ingest - const [, err] = await props.restreamer.UpsertIngest(_channelid, inputs, outputs, control); + const [, err] = await props.restreamer.UpsertIngest(_channelid, global, inputs, outputs, control); if (err !== null) { notify.Dispatch('error', 'save:ingest', i18n._(t`Failed to update ingest process (${err.message})`)); return false; diff --git a/src/views/Publication/Add.js b/src/views/Publication/Add.js index 0887aaa..890cd20 100644 --- a/src/views/Publication/Add.js +++ b/src/views/Publication/Add.js @@ -176,9 +176,9 @@ export default function Add(props) { const handleServiceDone = async () => { setSaving(true); - const [inputs, outputs] = helper.createInputsOutputs($sources, $settings.profiles, $settings.outputs); + const [global, inputs, outputs] = helper.createInputsOutputs($sources, $settings.profiles, $settings.outputs); - const [id, err] = await props.restreamer.CreateEgress(_channelid, $service, inputs, outputs, $settings.control); + const [id, err] = await props.restreamer.CreateEgress(_channelid, $service, global, inputs, outputs, $settings.control); if (err !== null) { setSaving(false); notify.Dispatch('error', 'save:egress:' + $service, i18n._(t`Failed to create publication service (${err.message})`)); @@ -380,20 +380,12 @@ export default function Add(props) { - + - - {service.name} + + + {service.name} + v{service.version} @@ -435,20 +427,12 @@ export default function Add(props) { - + - - {service.name} + + + {service.name} + v{service.version} @@ -480,20 +464,12 @@ export default function Add(props) { - + - - {service.name} + + + {service.name} + v{service.version} diff --git a/src/views/Publication/Edit.js b/src/views/Publication/Edit.js index 31c4269..9c01c10 100644 --- a/src/views/Publication/Edit.js +++ b/src/views/Publication/Edit.js @@ -218,9 +218,9 @@ export default function Edit(props) { const handleServiceDone = async () => { setSaving(true); - const [inputs, outputs] = helper.createInputsOutputs($sources, $settings.profiles, $settings.outputs); + const [global, inputs, outputs] = helper.createInputsOutputs($sources, $settings.profiles, $settings.outputs); - const [, err] = await props.restreamer.UpdateEgress(_channelid, id, inputs, outputs, $settings.control); + const [, err] = await props.restreamer.UpdateEgress(_channelid, id, global, inputs, outputs, $settings.control); if (err !== null) { setSaving(false); notify.Dispatch('error', 'save:egress:' + _service, i18n._(t`Failed to store publication service (${err.message})`)); @@ -394,20 +394,12 @@ export default function Edit(props) { - + - - {$service.name} + + + {$service.name} + v{$service.version} @@ -443,20 +435,12 @@ export default function Edit(props) { - + - - {$service.name} + + + {$service.name} + v{$service.version} @@ -516,20 +500,12 @@ export default function Edit(props) { - + - - {$service.name} + + + {$service.name} + v{$service.version} diff --git a/src/views/Publication/helper.js b/src/views/Publication/helper.js index 0a2f1f0..f59826b 100644 --- a/src/views/Publication/helper.js +++ b/src/views/Publication/helper.js @@ -35,7 +35,7 @@ export function createSourcesFromStreams(streams) { * @returns */ export function createInputsOutputs(sources, profiles, outputs) { - const [inpts, outpts] = M.createInputsOutputs(sources, profiles); + const [global, inpts, outpts] = M.createInputsOutputs(sources, profiles); const out = []; @@ -58,7 +58,7 @@ export function createInputsOutputs(sources, profiles, outputs) { out.push(o); } - return [inpts, out]; + return [global, inpts, out]; } /** * validateRequirements validates the requirements object the each From 2a8ec7b3484d69180d05a25d257b325528bd7298 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Wed, 29 Jun 2022 23:43:36 +0200 Subject: [PATCH 07/78] Add HLS version selection (Electra Player compatibility) --- src/misc/controls/HLS.js | 13 +++++++ src/utils/restreamer.js | 74 ++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/misc/controls/HLS.js b/src/misc/controls/HLS.js index 6658cb8..b1875ab 100644 --- a/src/misc/controls/HLS.js +++ b/src/misc/controls/HLS.js @@ -2,10 +2,12 @@ import React from 'react'; import { Trans } from '@lingui/macro'; 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 Checkbox from '../Checkbox'; +import Select from '../Select'; function init(settings) { const initSettings = { @@ -13,6 +15,7 @@ function init(settings) { segmentDuration: 2, listSize: 6, cleanup: true, + version: 3, ...settings, }; @@ -55,6 +58,16 @@ export default function Control(props) { */} + + + + M3U8 manifest version. Version 3 has the longest browser/client compatibility. + + '' + o)], cleanup: [ { - pattern: `memfs:/${channel.channelid}_*.ts`, - max_files: parseInt(control.hls.listSize) + 2, - max_file_age_seconds: control.hls.cleanup ? parseInt(control.hls.segmentDuration) * (parseInt(control.hls.listSize) + 2) : 0, + pattern: control.hls.version >= 7 ? `memfs:/${channel.channelid}_*.mp4` : `memfs:/${channel.channelid}_*.ts`, + max_files: parseInt(control.hls.listSize) + 6, + max_file_age_seconds: control.hls.cleanup ? parseInt(control.hls.segmentDuration) * (parseInt(control.hls.listSize) + 6) : 0, purge_on_delete: true, }, { pattern: `memfs:/${channel.channelid}.m3u8`, - max_file_age_seconds: control.hls.cleanup ? parseInt(control.hls.segmentDuration) * (parseInt(control.hls.listSize) + 2) : 0, + max_file_age_seconds: control.hls.cleanup ? parseInt(control.hls.segmentDuration) * (parseInt(control.hls.listSize) + 6) : 0, purge_on_delete: true, }, ], @@ -1481,25 +1481,57 @@ class Restreamer { output.options.push(...metadata_options); + // manifest versions + // https://developer.apple.com/documentation/http_live_streaming/about_the_ext-x-version_tag + // https://ffmpeg.org/ffmpeg-all.html#Options-53 + console.log(control.hls.version) if (control.hls.lhls === false) { // ordinary HLS - output.options.push( - '-f', - 'hls', - '-start_number', - '0', - '-hls_time', - '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', - '' + parseInt(control.hls.listSize), - '-hls_flags', - 'append_list+delete_segments', - '-hls_segment_filename', - `{memfs}/${channel.channelid}_%04d.ts`, - '-y', - '-method', - 'PUT' - ); + if (control.hls.version >= 6 && control.hls.version < 7) { + output.options.push( + '-f', 'hls', + '-start_number', '0', + '-hls_time', '' + parseInt(control.hls.segmentDuration), + '-hls_list_size', '' + parseInt(control.hls.listSize), + '-hls_flags', 'append_list+delete_segments+program_date_time+independent_segments', + '-hls_delete_threshold', '4', + '-hls_segment_filename', `{memfs}/${channel.channelid}_%04d.ts`, + '-segment_format_options', 'mpegts_flags=mpegts_copyts=1', + '-max_muxing_queue_size', '400', + '-y', + '-method', 'PUT' + ); + } else if (control.hls.version >= 7) { + output.options.push( + '-f', 'hls', + '-start_number', '0', + '-hls_time', '' + parseInt(control.hls.segmentDuration), + '-hls_list_size', '' + parseInt(control.hls.listSize), + '-hls_flags', 'append_list+delete_segments+program_date_time+independent_segments', + '-hls_delete_threshold', '4', + '-hls_segment_type', 'fmp4', + '-hls_fmp4_init_filename', `${channel.channelid}_init.mp4`, + '-hls_segment_filename', `{memfs}/${channel.channelid}_%04d.mp4`, + '-segment_format_options', 'mpegts_flags=mpegts_copyts=1', + '-max_muxing_queue_size', '400', + '-y', + '-method', 'PUT' + ); + } else { + output.options.push( + '-f', 'hls', + '-start_number', '0', + '-hls_time', '' + parseInt(control.hls.segmentDuration), + '-hls_list_size', '' + parseInt(control.hls.listSize), + '-hls_flags', 'append_list+delete_segments+program_date_time', + '-hls_delete_threshold', '4', + '-hls_segment_filename', `{memfs}/${channel.channelid}_%04d.ts`, + '-segment_format_options', 'mpegts_flags=mpegts_copyts=1', + '-max_muxing_queue_size', '400', + '-y', + '-method', 'PUT' + ); + }; } else { // Low Latency HLS output.address = `{memfs}/${channel.channelid}.mpd`; From 7239bf4d66640bdbca64ce26992f8063822acc8a Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Thu, 30 Jun 2022 09:48:44 +0200 Subject: [PATCH 08/78] Cosmetics --- src/misc/coders/Encoders/audio/Copy.js | 9 +-- src/misc/controls/HLS.js | 10 ++- src/utils/restreamer.js | 104 ++++++++++++++++--------- 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/src/misc/coders/Encoders/audio/Copy.js b/src/misc/coders/Encoders/audio/Copy.js index d6f90cf..9065c38 100644 --- a/src/misc/coders/Encoders/audio/Copy.js +++ b/src/misc/coders/Encoders/audio/Copy.js @@ -2,11 +2,10 @@ import React from 'react'; function createMapping(settings, stream) { const local = ['-codec:a', 'copy']; - /* - if(stream.codec === 'aac') { - local.push('-bsf:a', 'aac_adtstoasc'); - } -*/ + + //if (stream.codec === 'aac') { + // local.push('-bsf:a', 'aac_adtstoasc'); + //} const mapping = { global: [], diff --git a/src/misc/controls/HLS.js b/src/misc/controls/HLS.js index b1875ab..03eb0b4 100644 --- a/src/misc/controls/HLS.js +++ b/src/misc/controls/HLS.js @@ -61,11 +61,15 @@ export default function Control(props) { - M3U8 manifest version. Version 3 has the longest browser/client compatibility. + M3U8 manifest version. Version 3 has the best browser/client compatibility. diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 1be85a3..71c993e 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -1484,54 +1484,86 @@ class Restreamer { // manifest versions // https://developer.apple.com/documentation/http_live_streaming/about_the_ext-x-version_tag // https://ffmpeg.org/ffmpeg-all.html#Options-53 - console.log(control.hls.version) + console.log(control.hls.version); if (control.hls.lhls === false) { // ordinary HLS - if (control.hls.version >= 6 && control.hls.version < 7) { + if (control.hls.version === 6) { output.options.push( - '-f', 'hls', - '-start_number', '0', - '-hls_time', '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', '' + parseInt(control.hls.listSize), - '-hls_flags', 'append_list+delete_segments+program_date_time+independent_segments', - '-hls_delete_threshold', '4', - '-hls_segment_filename', `{memfs}/${channel.channelid}_%04d.ts`, - '-segment_format_options', 'mpegts_flags=mpegts_copyts=1', - '-max_muxing_queue_size', '400', + '-f', + 'hls', + '-start_number', + '0', + '-hls_time', + '' + parseInt(control.hls.segmentDuration), + '-hls_list_size', + '' + parseInt(control.hls.listSize), + '-hls_flags', + 'append_list+delete_segments+program_date_time+independent_segments', + '-hls_delete_threshold', + '4', + '-hls_segment_filename', + `{memfs}/${channel.channelid}_%04d.ts`, + '-segment_format_options', + 'mpegts_flags=mpegts_copyts=1', + '-max_muxing_queue_size', + '400', '-y', - '-method', 'PUT' + '-method', + 'PUT' ); - } else if (control.hls.version >= 7) { + } else if (control.hls.version === 7) { output.options.push( - '-f', 'hls', - '-start_number', '0', - '-hls_time', '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', '' + parseInt(control.hls.listSize), - '-hls_flags', 'append_list+delete_segments+program_date_time+independent_segments', - '-hls_delete_threshold', '4', - '-hls_segment_type', 'fmp4', - '-hls_fmp4_init_filename', `${channel.channelid}_init.mp4`, - '-hls_segment_filename', `{memfs}/${channel.channelid}_%04d.mp4`, - '-segment_format_options', 'mpegts_flags=mpegts_copyts=1', - '-max_muxing_queue_size', '400', + '-f', + 'hls', + '-start_number', + '0', + '-hls_time', + '' + parseInt(control.hls.segmentDuration), + '-hls_list_size', + '' + parseInt(control.hls.listSize), + '-hls_flags', + 'append_list+delete_segments+program_date_time+independent_segments', + '-hls_delete_threshold', + '4', + '-hls_segment_type', + 'fmp4', + '-hls_fmp4_init_filename', + `${channel.channelid}_init.mp4`, + '-hls_segment_filename', + `{memfs}/${channel.channelid}_%04d.mp4`, + '-segment_format_options', + 'mpegts_flags=mpegts_copyts=1', + '-max_muxing_queue_size', + '400', '-y', - '-method', 'PUT' + '-method', + 'PUT' ); } else { output.options.push( - '-f', 'hls', - '-start_number', '0', - '-hls_time', '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', '' + parseInt(control.hls.listSize), - '-hls_flags', 'append_list+delete_segments+program_date_time', - '-hls_delete_threshold', '4', - '-hls_segment_filename', `{memfs}/${channel.channelid}_%04d.ts`, - '-segment_format_options', 'mpegts_flags=mpegts_copyts=1', - '-max_muxing_queue_size', '400', + '-f', + 'hls', + '-start_number', + '0', + '-hls_time', + '' + parseInt(control.hls.segmentDuration), + '-hls_list_size', + '' + parseInt(control.hls.listSize), + '-hls_flags', + 'append_list+delete_segments+program_date_time', + '-hls_delete_threshold', + '4', + '-hls_segment_filename', + `{memfs}/${channel.channelid}_%04d.ts`, + '-segment_format_options', + 'mpegts_flags=mpegts_copyts=1', + '-max_muxing_queue_size', + '400', '-y', - '-method', 'PUT' + '-method', + 'PUT' ); - }; + } } else { // Low Latency HLS output.address = `{memfs}/${channel.channelid}.mpd`; From 16e669f05d188f1e9649986a6ecf18bc2c71b830 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Thu, 30 Jun 2022 14:49:24 +0200 Subject: [PATCH 09/78] Mod adds a more fluent version compatible with tee_muxer --- src/utils/restreamer.js | 222 +++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 116 deletions(-) diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 71c993e..b10d139 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -1481,127 +1481,117 @@ class Restreamer { output.options.push(...metadata_options); - // manifest versions + // Manifest versions // https://developer.apple.com/documentation/http_live_streaming/about_the_ext-x-version_tag // https://ffmpeg.org/ffmpeg-all.html#Options-53 - console.log(control.hls.version); - if (control.hls.lhls === false) { - // ordinary HLS - if (control.hls.version === 6) { - output.options.push( - '-f', - 'hls', - '-start_number', - '0', - '-hls_time', - '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', - '' + parseInt(control.hls.listSize), - '-hls_flags', - 'append_list+delete_segments+program_date_time+independent_segments', - '-hls_delete_threshold', - '4', - '-hls_segment_filename', - `{memfs}/${channel.channelid}_%04d.ts`, - '-segment_format_options', - 'mpegts_flags=mpegts_copyts=1', - '-max_muxing_queue_size', - '400', - '-y', - '-method', - 'PUT' - ); - } else if (control.hls.version === 7) { - output.options.push( - '-f', - 'hls', - '-start_number', - '0', - '-hls_time', - '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', - '' + parseInt(control.hls.listSize), - '-hls_flags', - 'append_list+delete_segments+program_date_time+independent_segments', - '-hls_delete_threshold', - '4', - '-hls_segment_type', - 'fmp4', - '-hls_fmp4_init_filename', - `${channel.channelid}_init.mp4`, - '-hls_segment_filename', - `{memfs}/${channel.channelid}_%04d.mp4`, - '-segment_format_options', - 'mpegts_flags=mpegts_copyts=1', - '-max_muxing_queue_size', - '400', - '-y', - '-method', - 'PUT' - ); + + // Returns the raw l/hls parameters for a EXT-X-VERSION + function hlsParams(lhls, version) { + if (lhls) { + // lhls + switch (version) { + default: + return [ + ['f', 'dash'], + ['strict', 'experimental'], + ['hls_playlist', '1'], + ['init_seg_name', `init-${channel.channelid}.$ext$`], + ['media_seg_name', `chunk-${channel.channelid}-$Number%05d$.$ext$`], + ['master_m3u8_publish_rate', '1'], + ['adaptation_sets', 'id=0,streams=v id=1,streams=a'], + ['lhls', '1'], + ['streaming', '1'], + ['seg_duration', '' + parseInt(control.hls.segmentDuration)], + ['frag_duration', '0.5'], + ['use_template', '1'], + ['remove_at_exit', '0'], + ['window_size', '' + parseInt(control.hls.listSize)], + ['http_persistent', '0'], + ['method', 'PUT'], + ]; + } } else { - output.options.push( - '-f', - 'hls', - '-start_number', - '0', - '-hls_time', - '' + parseInt(control.hls.segmentDuration), - '-hls_list_size', - '' + parseInt(control.hls.listSize), - '-hls_flags', - 'append_list+delete_segments+program_date_time', - '-hls_delete_threshold', - '4', - '-hls_segment_filename', - `{memfs}/${channel.channelid}_%04d.ts`, - '-segment_format_options', - 'mpegts_flags=mpegts_copyts=1', - '-max_muxing_queue_size', - '400', - '-y', - '-method', - 'PUT' - ); + // hls + switch (version) { + case 6: + return [ + ['f', 'hls'], + ['start_number', '0'], + ['hls_time', '' + parseInt(control.hls.segmentDuration)], + ['hls_list_size', '' + parseInt(control.hls.listSize)], + ['hls_flags', 'append_list+delete_segments+program_date_time+independent_segments'], + ['hls_delete_threshold', '4'], + ['hls_segment_filename', `{memfs}/${channel.channelid}_%04d.ts`], + ['segment_format_options', 'mpegts_flags=mpegts_copyts=1'], + ['max_muxing_queue_size', '400'], + ['method', 'PUT'], + ]; + + case 7: + return [ + ['f', 'hls'], + ['start_number', '0'], + ['hls_time', '' + parseInt(control.hls.segmentDuration)], + ['hls_list_size', '' + parseInt(control.hls.listSize)], + ['hls_flags', 'append_list+delete_segments+program_date_time+independent_segments'], + ['hls_delete_threshold', '4'], + ['hls_segment_type', 'fmp4'], + ['hls_fmp4_init_filename', `${channel.channelid}_init.mp4`], + ['hls_segment_filename', `{memfs}/${channel.channelid}_%04d.mp4`], + ['segment_format_options', 'mpegts_flags=mpegts_copyts=1'], + ['max_muxing_queue_size', '400'], + ['method', 'PUT'], + ]; + + default: + // case 3 + return [ + ['f', 'hls'], + ['start_number', '0'], + ['hls_time', '' + parseInt(control.hls.segmentDuration)], + ['hls_list_size', '' + parseInt(control.hls.listSize)], + ['hls_flags', 'append_list+delete_segments+program_date_time'], + ['hls_delete_threshold', '4'], + ['hls_segment_filename', `{memfs}/${channel.channelid}_%04d.ts`], + ['segment_format_options', 'mpegts_flags=mpegts_copyts=1'], + ['max_muxing_queue_size', '400'], + ['method', 'PUT'], + ]; + } } + } + const hls_params_raw = hlsParams(control.hls.lhls, control.hls.version); + + // 'tee_muxer' is required for the delivery of one output to multiple endpoints + // http://ffmpeg.org/ffmpeg-all.html#tee-1 + const tee_muxer = false; + + // Returns the l/hls parameters with or without tee_muxer + let hls_params = []; + if (tee_muxer) { + // ['f=hls', 'start_number=0', ...] + for (let i in hls_params_raw) { + if (hls_params_raw[i][0] !== 'segment_format_options' && hls_params_raw[i][0] !== 'max_muxing_queue_size') { + hls_params = [...hls_params, hls_params_raw[i][0] + '=' + hls_params_raw[i][1]]; + } + } + // ['f=hls:start_number=0...] + // Switch to hls_params += string? + hls_params = '[' + hls_params.toString().replace(/,/g, ':') + ']' + `{memfs}/${channel.channelid}.m3u8`; } else { - // Low Latency HLS - output.address = `{memfs}/${channel.channelid}.mpd`; - output.options.push( - '-f', - 'dash', - '-strict', - 'experimental', - '-hls_playlist', - '1', - '-init_seg_name', - `init-${channel.channelid}.$ext$`, - '-media_seg_name', - `chunk-${channel.channelid}-$Number%05d$.$ext$`, - '-master_m3u8_publish_rate', - '1', - '-adaptation_sets', - 'id=0,streams=v id=1,streams=a', - '-lhls', - '1', - '-streaming', - '1', - '-seg_duration', - '' + parseInt(control.hls.segmentDuration), - '-frag_duration', - '0.5', - '-use_template', - '1', - '-remove_at_exit', - '0', - '-window_size', - '' + parseInt(control.hls.listSize), - '-http_persistent', - '0', - '-y', - '-method', - 'PUT' - ); + // ['-f', 'hls', '-start_number', '0', ...] + for (let i in hls_params_raw) { + hls_params = [...hls_params, '-' + hls_params_raw[i][0], hls_params_raw[i][1]]; + } + } + + // Pushes the hls parameters into the output options + if (tee_muxer) { + output.options.push("-tag:v", "7", "-tag:a", "10", "-f", "tee"); + // WARN: It is a magic function. Returns 'Invalid process config' and the process.id is lost (Core v16.8.0) + // output.address = hls_params; + } else { + output.options.concat(hls_params); } proc.output.push(output); From faa2cc1af2739cd4a5d7cfe2f04dca057988e97c Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Thu, 30 Jun 2022 16:03:41 +0200 Subject: [PATCH 10/78] Fix no-useless-concat + style --- src/utils/restreamer.js | 66 ++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index b10d139..c2c8095 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -1485,31 +1485,28 @@ class Restreamer { // https://developer.apple.com/documentation/http_live_streaming/about_the_ext-x-version_tag // https://ffmpeg.org/ffmpeg-all.html#Options-53 - // Returns the raw l/hls parameters for a EXT-X-VERSION - function hlsParams(lhls, version) { + // Returns the raw l/hls parameters for an EXT-X-VERSION + function GetHlsParams(lhls, version) { if (lhls) { // lhls - switch (version) { - default: - return [ - ['f', 'dash'], - ['strict', 'experimental'], - ['hls_playlist', '1'], - ['init_seg_name', `init-${channel.channelid}.$ext$`], - ['media_seg_name', `chunk-${channel.channelid}-$Number%05d$.$ext$`], - ['master_m3u8_publish_rate', '1'], - ['adaptation_sets', 'id=0,streams=v id=1,streams=a'], - ['lhls', '1'], - ['streaming', '1'], - ['seg_duration', '' + parseInt(control.hls.segmentDuration)], - ['frag_duration', '0.5'], - ['use_template', '1'], - ['remove_at_exit', '0'], - ['window_size', '' + parseInt(control.hls.listSize)], - ['http_persistent', '0'], - ['method', 'PUT'], - ]; - } + return [ + ['f', 'dash'], + ['strict', 'experimental'], + ['hls_playlist', '1'], + ['init_seg_name', `init-${channel.channelid}.$ext$`], + ['media_seg_name', `chunk-${channel.channelid}-$Number%05d$.$ext$`], + ['master_m3u8_publish_rate', '1'], + ['adaptation_sets', 'id=0,streams=v id=1,streams=a'], + ['lhls', '1'], + ['streaming', '1'], + ['seg_duration', '' + parseInt(control.hls.segmentDuration)], + ['frag_duration', '0.5'], + ['use_template', '1'], + ['remove_at_exit', '0'], + ['window_size', '' + parseInt(control.hls.listSize)], + ['http_persistent', '0'], + ['method', 'PUT'], + ]; } else { // hls switch (version) { @@ -1526,7 +1523,6 @@ class Restreamer { ['max_muxing_queue_size', '400'], ['method', 'PUT'], ]; - case 7: return [ ['f', 'hls'], @@ -1542,9 +1538,8 @@ class Restreamer { ['max_muxing_queue_size', '400'], ['method', 'PUT'], ]; - + // case 3 default: - // case 3 return [ ['f', 'hls'], ['start_number', '0'], @@ -1560,25 +1555,28 @@ class Restreamer { } } } - const hls_params_raw = hlsParams(control.hls.lhls, control.hls.version); + const hls_params_raw = GetHlsParams(control.hls.lhls, control.hls.version); // 'tee_muxer' is required for the delivery of one output to multiple endpoints // http://ffmpeg.org/ffmpeg-all.html#tee-1 const tee_muxer = false; // Returns the l/hls parameters with or without tee_muxer - let hls_params = []; + let hls_params = ''; if (tee_muxer) { - // ['f=hls', 'start_number=0', ...] + // ['f=hls:start_number=0...] for (let i in hls_params_raw) { if (hls_params_raw[i][0] !== 'segment_format_options' && hls_params_raw[i][0] !== 'max_muxing_queue_size') { - hls_params = [...hls_params, hls_params_raw[i][0] + '=' + hls_params_raw[i][1]]; + hls_params += hls_params_raw[i][0] + '=' + hls_params_raw[i][1]; + if (i < hls_params_raw.length - 1) { + hls_params += ':'; + } } } - // ['f=hls:start_number=0...] - // Switch to hls_params += string? - hls_params = '[' + hls_params.toString().replace(/,/g, ':') + ']' + `{memfs}/${channel.channelid}.m3u8`; + // ['f=hls:start_number=0...]address.m3u8 + hls_params = `[` + hls_params + `]{memfs}/${channel.channelid}.m3u8`; } else { + hls_params = []; // ['-f', 'hls', '-start_number', '0', ...] for (let i in hls_params_raw) { hls_params = [...hls_params, '-' + hls_params_raw[i][0], hls_params_raw[i][1]]; @@ -1587,7 +1585,7 @@ class Restreamer { // Pushes the hls parameters into the output options if (tee_muxer) { - output.options.push("-tag:v", "7", "-tag:a", "10", "-f", "tee"); + output.options.push('-tag:v', '7', '-tag:a', '10', '-f', 'tee'); // WARN: It is a magic function. Returns 'Invalid process config' and the process.id is lost (Core v16.8.0) // output.address = hls_params; } else { From cb2d486888240438f4280bdc36ba894da6ec0f12 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Thu, 30 Jun 2022 19:05:26 +0200 Subject: [PATCH 11/78] Fix Malformed AAC bitstream detected for hls version 7 + array merge --- src/utils/restreamer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index c2c8095..2fd6294 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -1524,6 +1524,10 @@ class Restreamer { ['method', 'PUT'], ]; case 7: + // fix Malformed AAC bitstream detected for hls version 7 + if (control.hls.version === 7 && output.options.includes('-codec:a') && output.options.includes('copy')) { + output.options.push('-bsf:a', 'aac_adtstoasc'); + } return [ ['f', 'hls'], ['start_number', '0'], @@ -1589,7 +1593,7 @@ class Restreamer { // WARN: It is a magic function. Returns 'Invalid process config' and the process.id is lost (Core v16.8.0) // output.address = hls_params; } else { - output.options.concat(hls_params); + output.options.push(...hls_params); } proc.output.push(output); From 0be3a7030464294cebe15b70293170de7fdcef3a Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Thu, 30 Jun 2022 19:09:45 +0200 Subject: [PATCH 12/78] Mod updates CHANGELOG --- CHANGELOG.md | 4 +++- package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d0af8b..4533846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,12 @@ # Restreamer-UI -#### v1.1.0 > v1.4.0 +#### v1.1.0 > v1.5.0 +- Add HLS version selection (Dwaynarang, Electra Player compatibility) - Add Owncast to publication services ([#369](https://github.com/datarhei/restreamer/issues/369)) - Add Telegram to publication services (thx Martin Held) - Add Polish translations (thx Robert Rykała) +- Mod Allow decoders and encoders to set global options - Fix process report naming - Fix publication service icon styles - Fix VAAPI encoder diff --git a/package.json b/package.json index a454a81..7f8b30d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "restreamer-ui", - "version": "1.4.0", + "version": "1.5.0", "bundle": "restreamer-v2.x.x", "private": false, "license": "Apache-2.0", From fd462775c171393041525b33b7d39ba72bb17e6a Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Thu, 30 Jun 2022 21:39:12 +0200 Subject: [PATCH 13/78] Slimming down HLS parameter assembly --- src/utils/restreamer.js | 45 ++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 2fd6294..2bad11b 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -1486,7 +1486,7 @@ class Restreamer { // https://ffmpeg.org/ffmpeg-all.html#Options-53 // Returns the raw l/hls parameters for an EXT-X-VERSION - function GetHlsParams(lhls, version) { + const getHLSParams = (lhls, version) => { if (lhls) { // lhls return [ @@ -1558,41 +1558,36 @@ class Restreamer { ]; } } - } - const hls_params_raw = GetHlsParams(control.hls.lhls, control.hls.version); + }; + const hls_params_raw = getHLSParams(control.hls.lhls, control.hls.version); - // 'tee_muxer' is required for the delivery of one output to multiple endpoints + // 'tee_muxer' is required for the delivery of one output to multiple endpoints without processing the input for each output // http://ffmpeg.org/ffmpeg-all.html#tee-1 const tee_muxer = false; // Returns the l/hls parameters with or without tee_muxer - let hls_params = ''; if (tee_muxer) { - // ['f=hls:start_number=0...] - for (let i in hls_params_raw) { - if (hls_params_raw[i][0] !== 'segment_format_options' && hls_params_raw[i][0] !== 'max_muxing_queue_size') { - hls_params += hls_params_raw[i][0] + '=' + hls_params_raw[i][1]; - if (i < hls_params_raw.length - 1) { - hls_params += ':'; + // f=hls:start_number=0... + const hls_params = hls_params_raw + .filter((o) => { + if (o[0] === 'segment_format_options' || o[0] === 'max_muxing_queue_size') { + return false; } - } - } + + return true; + }) + .map((o) => o[0] + '=' + o[1]) + .join(':'); + + output.options.push('-tag:v', '7', '-tag:a', '10', '-f', 'tee'); + // WARN: It is a magic function. Returns 'Invalid process config' and the process.id is lost (Core v16.8.0) <= this is not the case anymore with the latest dev branch // ['f=hls:start_number=0...]address.m3u8 - hls_params = `[` + hls_params + `]{memfs}/${channel.channelid}.m3u8`; + output.address = `[` + hls_params + `]{memfs}/${channel.channelid}.m3u8`; } else { - hls_params = []; // ['-f', 'hls', '-start_number', '0', ...] - for (let i in hls_params_raw) { - hls_params = [...hls_params, '-' + hls_params_raw[i][0], hls_params_raw[i][1]]; - } - } + // adding the '-' in front of the first option, then flatten everything + const hls_params = hls_params_raw.map((o) => ['-' + o[0], o[1]]).reduce((acc, val) => acc.concat(val), []); - // Pushes the hls parameters into the output options - if (tee_muxer) { - output.options.push('-tag:v', '7', '-tag:a', '10', '-f', 'tee'); - // WARN: It is a magic function. Returns 'Invalid process config' and the process.id is lost (Core v16.8.0) - // output.address = hls_params; - } else { output.options.push(...hls_params); } From 64d532e38b8c0076c8faf09cc5a18d5d13a2650d Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Fri, 1 Jul 2022 16:48:42 +0200 Subject: [PATCH 14/78] Remove trailing slash from Core address --- src/utils/api.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/utils/api.js b/src/utils/api.js index 81c31f1..57c0e14 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,5 +1,10 @@ class API { constructor(address) { + // Removes the / at the end + if (address.slice(-1) === '/') { + address = address.slice(0, -1); + } + this.base = '/api'; this.address = address; this.token = ''; From ad539c66900265c378bccb2796eb7502ea405636 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Fri, 1 Jul 2022 16:53:01 +0200 Subject: [PATCH 15/78] Update changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4533846..12ef7a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Restreamer-UI -#### v1.1.0 > v1.5.0 +#### v1.1.0 > v1.2.0 - Add HLS version selection (Dwaynarang, Electra Player compatibility) - Add Owncast to publication services ([#369](https://github.com/datarhei/restreamer/issues/369)) @@ -9,7 +9,8 @@ - Mod Allow decoders and encoders to set global options - Fix process report naming - Fix publication service icon styles -- Fix VAAPI encoder +- Fix VAAPI encoder +- Allow trailing slash on Core address #### v1.0.0 > v1.1.0 From ed1dc214242eaa2c2640cf94f192f9829409ce92 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Fri, 1 Jul 2022 16:56:15 +0200 Subject: [PATCH 16/78] Change version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7f8b30d..ae84d3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "restreamer-ui", - "version": "1.5.0", + "version": "1.2.0", "bundle": "restreamer-v2.x.x", "private": false, "license": "Apache-2.0", @@ -92,4 +92,4 @@ "url-parse@1.5.3": "patch:url-parse@npm:1.5.3#.yarn/patches/url-parse-npm-1.5.3-225ab9cae7.patch", "react-error-overlay": "6.0.9" } -} +} \ No newline at end of file From 73d2f79876426ac74e8b1a62eb343d9dbb9b076a Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Mon, 4 Jul 2022 20:26:06 +0200 Subject: [PATCH 17/78] Add SRT settings --- src/utils/restreamer.js | 18 ++++++ src/views/Settings.js | 118 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 2bad11b..75488aa 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -679,6 +679,13 @@ class Restreamer { token: '', name: '', }, + srt: { + enabled: false, + host: '', + local: 'localhost', + token: '', + passphrase: '', + }, hls: { secure: false, host: '', @@ -824,6 +831,17 @@ class Restreamer { config.source.network.rtmp.local += ':' + rtmp_port; } + // SRT + + config.source.network.srt.enabled = val.config.srt.enable; + config.source.network.srt.passphrase = val.config.srt.passphrase; + config.source.network.srt.token = val.config.srt.token; + + let [srt_host, srt_port] = splitHostPort(val.config.srt.address); + config.source.network.srt.local = srt_host.length !== 0 ? srt_host : 'localhost'; + config.source.network.srt.host += ':' + srt_port; + config.source.network.srt.local += ':' + srt_port; + // Memfs config.memfs.auth.enable = val.config.storage.memory.auth.enable; diff --git a/src/views/Settings.js b/src/views/Settings.js index fe5dff3..223961d 100644 --- a/src/views/Settings.js +++ b/src/views/Settings.js @@ -295,6 +295,54 @@ const configValues = { return null; }, }, + 'srt.enable': { + tab: 'srt', + set: (config, value) => { + config.srt.enable = !config.srt.enable; + }, + unset: (config) => { + delete config.srt.enable; + }, + validate: (config) => { + return null; + }, + }, + 'srt.address': { + tab: 'srt', + set: (config, value) => { + config.srt.address = value; + }, + unset: (config) => { + delete config.srt.address; + }, + validate: (config) => { + return null; + }, + }, + 'srt.passphrase': { + tab: 'srt', + set: (config, value) => { + config.srt.token = value; + }, + unset: (config) => { + delete config.srt.token; + }, + validate: (config) => { + return null; + }, + }, + 'srt.token': { + tab: 'srt', + set: (config, value) => { + config.srt.token = value; + }, + unset: (config) => { + delete config.srt.token; + }, + validate: (config) => { + return null; + }, + }, 'storage.cors.allow_all': { tab: 'storage', set: (config, value) => { @@ -638,6 +686,7 @@ export default function Settings(props) { playback: { errors: false, messages: [] }, storage: { errors: false, messages: [] }, rtmp: { errors: false, messages: [] }, + srt: { errors: false, messages: [] }, logging: { errors: false, messages: [] }, service: { errors: false, messages: [] }, }); @@ -703,9 +752,10 @@ export default function Settings(props) { config.tls.auto = false; } - config.tls.address = config.tls.address.split(':').join(''); config.address = config.address.split(':').join(''); + config.tls.address = config.tls.address.split(':').join(''); config.rtmp.address = config.rtmp.address.split(':').join(''); + config.srt.address = config.srt.address.split(':').join(''); if (config.tls.auto === true) { config.tls.enable = true; @@ -856,9 +906,11 @@ export default function Settings(props) { config.sessions.session_timeout_sec = toInt(config.sessions.session_timeout_sec); config.sessions.max_bitrate_mbit = toInt(config.sessions.max_bitrate_mbit); config.sessions.max_sessions = toInt(config.sessions.max_sessions); - config.tls.address = ':' + config.tls.address; + config.address = ':' + config.address; + config.tls.address = ':' + config.tls.address; config.rtmp.address = ':' + config.rtmp.address; + config.srt.address = ':' + config.srt.address; if (config.tls.auto === true) { config.tls.enable = true; @@ -1144,6 +1196,7 @@ export default function Settings(props) { {$expert === true && Playback} value="playback" errors={$tabs.playback.errors} />} {$expert === true && Storage} value="storage" errors={$tabs.storage.errors} />} RTMP/S} value="rtmp" errors={$tabs.rtmp.errors} /> + SRT} value="srt" errors={$tabs.srt.errors} /> {$expert === true && Logging} value="logging" errors={$tabs.logging.errors} />} @@ -1839,6 +1892,67 @@ export default function Settings(props) { + + + + + SRT + + + + SRT server} + checked={config.srt.enable} + disabled={env('srt.enable')} + onChange={handleChange('srt.enable')} + />{' '} + {env('srt.enable') && } + + + + + + + Port} + env={env('srt.address')} + disabled={env('srt.address') || !config.srt.enable} + value={config.srt.address} + onChange={handleChange('srt.address')} + /> + + + SRT server listen address. + + + + Token} + env={env('srt.token')} + disabled={env('srt.token') || !config.srt.enable} + value={config.srt.token} + onChange={handleChange('srt.token')} + /> + + + SRT token for publishing and playing. The token is the value of the streamid parameter 'token.' + + + + Passphrase} + env={env('srt.passphrase')} + disabled={env('srt.passphrase') || !config.srt.enable} + value={config.srt.passphrase} + onChange={handleChange('srt.passphrase')} + /> + + + Passphrase for SRT encryption. + + + + From 9f96959315eda887a695b1d896fbedee5257f737 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Mon, 4 Jul 2022 20:27:27 +0200 Subject: [PATCH 18/78] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12ef7a6..8db1bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### v1.1.0 > v1.2.0 +- Add SRT settings - Add HLS version selection (Dwaynarang, Electra Player compatibility) - Add Owncast to publication services ([#369](https://github.com/datarhei/restreamer/issues/369)) - Add Telegram to publication services (thx Martin Held) From 56b64e90da357748271ff4f7497e849004c55d10 Mon Sep 17 00:00:00 2001 From: Jan Stabenow Date: Tue, 5 Jul 2022 13:20:54 +0200 Subject: [PATCH 19/78] Fix srt passphrase --- src/views/Settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/Settings.js b/src/views/Settings.js index 223961d..b13c39a 100644 --- a/src/views/Settings.js +++ b/src/views/Settings.js @@ -322,10 +322,10 @@ const configValues = { 'srt.passphrase': { tab: 'srt', set: (config, value) => { - config.srt.token = value; + config.srt.passphrase = value; }, unset: (config) => { - delete config.srt.token; + delete config.srt.passphrase; }, validate: (config) => { return null; From 20809bfc01478d5649e9f0bc14073e348760f6cf Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Wed, 6 Jul 2022 12:21:52 +0200 Subject: [PATCH 20/78] Add SRT push option --- src/utils/restreamer.js | 3 + src/views/Edit/Sources/Network.js | 448 +++++++++++++------ src/views/Edit/Wizard/Sources/InternalSRT.js | 98 ++++ src/views/Edit/Wizard/Sources/index.js | 2 + src/views/Edit/Wizard/index.js | 11 +- 5 files changed, 415 insertions(+), 147 deletions(-) create mode 100644 src/views/Edit/Wizard/Sources/InternalSRT.js diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 75488aa..e337de1 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -837,6 +837,8 @@ class Restreamer { config.source.network.srt.passphrase = val.config.srt.passphrase; config.source.network.srt.token = val.config.srt.token; + config.source.network.srt.host = config.hostname; + let [srt_host, srt_port] = splitHostPort(val.config.srt.address); config.source.network.srt.local = srt_host.length !== 0 ? srt_host : 'localhost'; config.source.network.srt.host += ':' + srt_port; @@ -862,6 +864,7 @@ class Restreamer { config.source.network.rtmp.name = this.channel.channelid; config.source.network.hls.name = this.channel.channelid; + config.source.network.srt.name = this.channel.channelid; return config; } diff --git a/src/views/Edit/Sources/Network.js b/src/views/Edit/Sources/Network.js index 2ceb2af..3aa0855 100644 --- a/src/views/Edit/Sources/Network.js +++ b/src/views/Edit/Sources/Network.js @@ -16,8 +16,10 @@ import Icon from '@mui/icons-material/AccountTree'; import MenuItem from '@mui/material/MenuItem'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; +import WarningIcon from '@mui/icons-material/Warning'; import BoxTextarea from '../../../misc/BoxTextarea'; +import BoxText from '../../../misc/BoxText'; import Checkbox from '../../../misc/Checkbox'; import FormInlineButton from '../../../misc/FormInlineButton'; import MultiSelect from '../../../misc/MultiSelect'; @@ -84,6 +86,7 @@ const initConfig = (initialConfig) => { const config = { rtmp: {}, + srt: {}, hls: {}, ...initialConfig, }; @@ -99,6 +102,16 @@ const initConfig = (initialConfig) => { ...config.rtmp, }; + config.srt = { + enabled: false, + host: 'localhost', + local: 'localhost', + token: '', + passphrase: '', + name: '', + ...config.srt, + }; + config.hls = { secure: false, host: 'localhost', @@ -127,11 +140,20 @@ const initSkills = (initialSkills) => { ...skills.version, }; + skills.formats = { + demuxers: [], + ...skills.formats, + }; + skills.protocols = { input: [], ...skills.protocols, }; + if (skills.formats.demuxers.includes('rtsp')) { + skills.protocols.input.push('rtsp'); + } + return skills; }; @@ -158,8 +180,12 @@ const createInputs = (settings, config, skills) => { if (settings.mode === 'push') { if (settings.push.type === 'hls') { input.address = getLocalHLS(config); - } else { + } else if (settings.push.type === 'rtmp') { input.address = getLocalRTMP(config); + } else if (settings.push.type === 'srt') { + input.address = getLocalSRT(config); + } else { + input.address = ''; } } else { input.address = settings.address; @@ -285,6 +311,26 @@ const isAuthProtocol = (url) => { return false; }; +const isSupportedProtocol = (url, supportedProtocols) => { + const protocol = getProtocol(url); + if (protocol.length === 0) { + return 0; + } + + if (!supportedProtocols.includes(protocol)) { + return -1; + } + + return 1; +}; + +const getHLSAddress = (host, credentials, name, secure) => { + // Test for IPv6 addresses and put brackets around + let url = 'http' + (secure ? 's' : '') + '://' + (credentials.length !== 0 ? credentials + '@' : '') + host + '/memfs/ingest/' + name + '.m3u8'; + + return url; +}; + const getRTMPAddress = (host, app, name, token, secure) => { let url = 'rtmp' + (secure ? 's' : '') + '://' + host + app + '/' + name + '.stream'; @@ -295,27 +341,36 @@ const getRTMPAddress = (host, app, name, token, secure) => { return url; }; -const getRTMP = (config, name) => { - const url = getRTMPAddress(config.rtmp.host, config.rtmp.app, config.rtmp.name, config.rtmp.token, config.rtmp.secure); +const getSRTAddress = (host, name, token, passphrase) => { + let url = + 'srt' + + '://' + + host + + '?mode=caller&transtype=live&streamid=#!:m=publish,r=' + + name + + (token.length !== 0 ? ',token=' + encodeURIComponent(token) : ''); + + if (passphrase.length !== 0) { + url += '&passphrase=' + encodeURIComponent(passphrase); + } - return [url]; + return url; }; -const getLocalRTMP = (config, name) => { - let url = getRTMPAddress(config.rtmp.local, config.rtmp.app, config.rtmp.name, config.rtmp.token, config.rtmp.secure); +const getHLS = (config, name) => { + const url = getHLSAddress(config.hls.host, config.hls.credentials, config.hls.name, config.hls.secure); - return url; + return [url]; }; -const getHLSAddress = (host, credentials, name, secure) => { - // Test for IPv6 addresses and put brackets around - let url = 'http' + (secure ? 's' : '') + '://' + (credentials.length !== 0 ? credentials + '@' : '') + host + '/memfs/ingest/' + name + '.m3u8'; +const getRTMP = (config) => { + const url = getRTMPAddress(config.rtmp.host, config.rtmp.app, config.rtmp.name, config.rtmp.token, config.rtmp.secure); - return url; + return [url]; }; -const getHLS = (config, name) => { - const url = getHLSAddress(config.hls.host, config.hls.credentials, config.hls.name, config.hls.secure); +const getSRT = (config) => { + const url = getSRTAddress(config.srt.host, config.srt.name, config.srt.token, config.srt.passphrase); return [url]; }; @@ -326,6 +381,14 @@ const getLocalHLS = (config, name) => { return url; }; +const getLocalRTMP = (config) => { + return getRTMPAddress(config.rtmp.local, config.rtmp.app, config.rtmp.name, config.rtmp.token, config.rtmp.secure); +}; + +const getLocalSRT = (config) => { + return getSRTAddress(config.srt.local, config.srt.name, config.srt.token, config.srt.passphrase); +}; + const isValidURL = (address) => { const protocol = getProtocolClass(address); if (protocol.length === 0) { @@ -340,6 +403,7 @@ function Pull(props) { const settings = props.settings; const protocolClass = getProtocolClass(settings.address); const authProtocol = isAuthProtocol(settings.address); + const supportedProtocol = isSupportedProtocol(settings.address, props.skills.protocols.input); return ( @@ -361,53 +425,132 @@ function Pull(props) { Supports HTTP (HLS, DASH), RTP, RTSP, RTMP, SRT and more. - {authProtocol && ( - - - Username} - value={settings.username} - onChange={props.onChange('', 'username')} - /> - - Username for the device. - - - - Password} - value={settings.password} - onChange={props.onChange('', 'password')} - /> - - Password for the device. - - - - )} - - - }> + {supportedProtocol === -1 && ( + + + - Advanced settings + This protocol is unknown or not supported by the available FFmpeg binary. - - - - {protocolClass === 'rtsp' && ( - + + + )} + {supportedProtocol === 1 && ( + + {authProtocol && ( + + + Username} + value={settings.username} + onChange={props.onChange('', 'username')} + /> + + Username for the device. + + + + Password} + value={settings.password} + onChange={props.onChange('', 'password')} + /> + + Password for the device. + + + + )} + + + }> + + Advanced settings + + + + + {protocolClass === 'rtsp' && ( + + + + RTSP + + + + UDP transport} + checked={settings.rtsp.udp} + onChange={props.onChange('rtsp', 'udp')} + /> + + + Socket timeout (microseconds)} + value={settings.rtsp.stimeout} + onChange={props.onChange('rtsp', 'stimeout')} + /> + + + )} + {protocolClass === 'http' && ( + + + + HTTP and HTTPS + + + + Read input at native speed} + checked={settings.http.readNative} + onChange={props.onChange('http', 'readNative')} + /> + Force input framerate} + checked={settings.http.forceFramerate} + onChange={props.onChange('http', 'forceFramerate')} + /> + + {settings.http.forceFramerate === true && ( + + Framerate} + value={settings.http.framerate} + onChange={props.onChange('http', 'framerate')} + /> + + )} + + + + + )} - RTSP + General - - UDP transport} checked={settings.rtsp.udp} onChange={props.onChange('rtsp', 'udp')} /> - Socket timeout (microseconds)} - value={settings.rtsp.stimeout} - onChange={props.onChange('rtsp', 'stimeout')} - /> - - - )} - {protocolClass === 'http' && ( - - - - HTTP and HTTPS - - - - Read input at native speed} - checked={settings.http.readNative} - onChange={props.onChange('http', 'readNative')} - /> - Force input framerate} - checked={settings.http.forceFramerate} - onChange={props.onChange('http', 'forceFramerate')} + label="thread_queue_size" + value={settings.general.thread_queue_size} + onChange={props.onChange('general', 'thread_queue_size')} /> - {settings.http.forceFramerate === true && ( - - Framerate} - value={settings.http.framerate} - onChange={props.onChange('http', 'framerate')} - /> - - )} - + + + + + + + + + + + - - )} - - - General - - - - - - - - - - - - - - - - - - - - - - + + + + + + )} - + Probe @@ -513,27 +595,51 @@ function Push(props) { const classes = useStyles(); const settings = props.settings; + //const supportsHLS = isSupportedProtocol('http://', props.skills.protocols.input); + const supportsRTMP = isSupportedProtocol('rtmp://', props.skills.protocols.input); + const supportsSRT = isSupportedProtocol('srt://', props.skills.protocols.input); + + if (!supportsRTMP && supportsSRT) { + return ( + + + + + + The available FFmpeg binary doesn't support any of the required protocols. + + + + + ); + } + return ( - {settings.push.type === 'rtmp' ? : settings.push.type === 'hls' ? : null} + {settings.push.type === 'rtmp' && } + {settings.push.type === 'hls' && } + {settings.push.type === 'srt' && } ); } function PushHLS(props) { const classes = useStyles(); - const settings = props.settings; const config = props.config; - const HLSs = getHLS(config, settings.push.name); + const HLSs = getHLS(config); return ( @@ -559,7 +665,6 @@ function PushHLS(props) { function PushRTMP(props) { const classes = useStyles(); const navigate = useNavigate(); - const settings = props.settings; const config = props.config; let form = null; @@ -580,7 +685,7 @@ function PushRTMP(props) { ); } else { - const RTMPs = getRTMP(config, settings.push.name); + const RTMPs = getRTMP(config); form = ( @@ -606,6 +711,55 @@ function PushRTMP(props) { return form; } +function PushSRT(props) { + const classes = useStyles(); + const navigate = useNavigate(); + const config = props.config; + + let form = null; + + if (config.srt.enabled === false) { + form = ( + + + + SRT server is not enabled + + + + + + + ); + } else { + const SRTs = getSRT(config); + + form = ( + + + + Send stream to this address: + + + + +