"bootstrap": "^4.1.3",
"buffer": "^5.1.0",
"cache-chunk-store": "^3.0.0",
- "codelyzer": "^5.0.0",
"core-js": "^3.0.0",
"css-loader": "^2.1.1",
"dexie": "^2.0.4",
"stream-http": "^3.0.0",
"terser-webpack-plugin": "^1.1.0",
"tslint": "^5.7.0",
+ "tslint-angular": "^1.1.2",
"tslint-config-standard": "^8.0.1",
"typescript": "3.2",
"video.js": "^7",
import { Subscription } from 'rxjs'
import { AuthService, Notifier, RedirectService } from '@app/core'
import { User, UserRight } from '../../../../shared'
-import { I18n } from '@ngx-translate/i18n-polyfill'
@Component({
templateUrl: './accounts.component.html',
<div i18n class="title-page title-page-single">
- Created {{pagination.totalItems}} playlists
+ Created {{ pagination.totalItems }} playlists
</div>
<div i18n class="no-results" *ngIf="pagination.totalItems === 0">This channel does not have playlists.</div>
const isDirty = control.dirty || forceCheck === true
if (control && isDirty && !control.valid) {
const messages = validationMessages[ field ]
- for (const key in control.errors) {
+ for (const key of Object.keys(control.errors)) {
formErrors[ field ] += messages[ key ] + ' '
}
}
// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
function objectToFormData (obj: any, form?: FormData, namespace?: string) {
- let fd = form || new FormData()
+ const fd = form || new FormData()
let formKey
- for (let key of Object.keys(obj)) {
+ for (const key of Object.keys(obj)) {
if (namespace) formKey = `${namespace}[${key}]`
else formKey = key
const markdownIt = new MarkdownItClass('zero', { linkify: true, breaks: true })
- for (let rule of rules) {
+ for (const rule of rules) {
markdownIt.enable(rule)
}
<a *ngIf="accountLink" tabindex="-1" class="video-info-account" [routerLink]="[ '/accounts', video.byAccount ]">{{ video.byAccount }}</a>
<span *ngIf="!accountLink" tabindex="-1" class="video-info-account">{{ video.byAccount }}</span>
- <span tabindex="-1" class="video-info-timestamp">{{ formatTimestamp(video)}}</span>
+ <span tabindex="-1" class="video-info-timestamp">{{ formatTimestamp(video) }}</span>
</div>
</a>
</div>
<span class="dropdown-item" (click)="removeFromPlaylist(video)">
- <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete from {{playlist?.displayName}}</ng-container>
+ <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete from {{ playlist?.displayName }}</ng-container>
</span>
</div>
</div>
<img alt="" [attr.aria-labelledby]="playlist.displayName" [attr.src]="playlist.thumbnailUrl" />
<div class="miniature-playlist-info-overlay">
- <ng-container i18n>{playlist.videosLength, plural, =0 {No videos} =1 {1 video} other {{{playlist.videosLength}} videos}}</ng-container>
+ <ng-container i18n>{playlist.videosLength, plural, =0 {No videos} =1 {1 video} other {{{ playlist.videosLength }} videos}}</ng-container>
</div>
<div class="play-overlay">
<div class="playlist-by-index">
<div class="playlist-by">{{ playlist.ownerBy }}</div>
<div class="playlist-index">
- <span>{{currentPlaylistPosition}}</span><span>{{playlistPagination.totalItems}}</span>
+ <span>{{ currentPlaylistPosition }}</span><span>{{ playlistPagination.totalItems }}</span>
</div>
</div>
</div>
if (i === max - 1) return segment.url
- let newBaseUrl = baseUrls[i]
- let middlePart = newBaseUrl.endsWith('/') ? '' : '/'
+ const newBaseUrl = baseUrls[i]
+ const middlePart = newBaseUrl.endsWith('/') ? '' : '/'
return newBaseUrl + middlePart + basename(segment.url)
}
const minuteSymbol = (symbol || 'm')
const secondsSymbol = full ? '' : 's'
- let hours = Math.floor(seconds / 3600)
+ const hours = Math.floor(seconds / 3600)
if (hours >= 1) time = hours + hourSymbol
else if (full) time = '0' + hourSymbol
seconds %= 3600
- let minutes = Math.floor(seconds / 60)
+ const minutes = Math.floor(seconds / 60)
if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol
else if (minutes >= 1) time += minutes + minuteSymbol
else if (full) time += '00' + minuteSymbol
private addClickListener (component: any) {
component.on('click', () => {
- let children = this.menu.children()
+ const children = this.menu.children()
for (const child of children) {
if (component !== child) {
onDisposeSettingsItem (event: any, name: string) {
if (name === undefined) {
- let children = this.menu.children()
+ const children = this.menu.children()
while (children.length > 0) {
children[0].dispose()
this.addClass('vjs-hidden')
} else {
- let item = this.menu.getChild(name)
+ const item = this.menu.getChild(name)
if (item) {
item.dispose()
return
}
- let offset = this.options_.setup.maxHeightOffset
- let maxHeight = this.playerComponent.el_.offsetHeight - offset
+ const offset = this.options_.setup.maxHeightOffset
+ const maxHeight = this.playerComponent.el_.offsetHeight - offset
if (height > maxHeight) {
height = maxHeight
buildMenu () {
this.menu = new Menu(this.player())
this.menu.addClass('vjs-main-menu')
- let entries = this.options_.entries
+ const entries = this.options_.entries
if (entries.length === 0) {
this.addClass('vjs-hidden')
return
}
- for (let entry of entries) {
+ for (const entry of entries) {
this.addMenuItem(entry, this.options_)
}
}
options.name = toTitleCase(entry)
- let settingsMenuItem = new SettingsMenuItem(this.player(), options, entry, this as any)
+ const settingsMenuItem = new SettingsMenuItem(this.player(), options, entry, this as any)
this.menu.addChild(settingsMenuItem)
}
resetChildren () {
- for (let menuChild of this.menu.children()) {
+ for (const menuChild of this.menu.children()) {
menuChild.reset()
}
}
* Hide all the sub menus
*/
hideChildren () {
- for (let menuChild of this.menu.children()) {
+ for (const menuChild of this.menu.children()) {
menuChild.hideSubMenu()
}
}
* @method PrefixedEvent
*/
PrefixedEvent (element: any, type: any, callback: any, action = 'addEvent') {
- let prefix = ['webkit', 'moz', 'MS', 'o', '']
+ const prefix = ['webkit', 'moz', 'MS', 'o', '']
for (let p = 0; p < prefix.length; p++) {
if (!prefix[p]) {
update (event?: any) {
let target: HTMLElement = null
- let subMenu = this.subMenu.name()
+ const subMenu = this.subMenu.name()
if (event && event.type === 'tap') {
target = event.target
setTimeout(() => this.settingsSubMenuValueEl_.innerHTML = this.subMenu.labelEl_.innerHTML, 250)
} else {
// Loop trough the submenu items to find the selected child
- for (let subMenuItem of this.subMenu.menu.children_) {
+ for (const subMenuItem of this.subMenu.menu.children_) {
if (!(subMenuItem instanceof component)) {
continue
}
}
bindClickEvents () {
- for (let item of this.subMenu.menu.children()) {
+ for (const item of this.subMenu.menu.children()) {
if (!(item instanceof component)) {
continue
}
}
setMargin () {
- let [width] = this.size
+ const [ width ] = this.size
this.settingsSubMenuEl_.style.marginRight = `-${width}px`
}
// Chunk in store
this.db.transaction('r', this.db.chunks, async () => {
const result = await this.db.chunks.get({ id: index })
- if (result === undefined) return cb(null, new Buffer(0))
+ if (result === undefined) return cb(null, Buffer.alloc(0))
const buf = result.buf
if (!opts) return this.nextTick(cb, null, buf)
}
if (this.db) {
- await this.db.close()
+ this.db.close()
await this.dropDatabase(this.databaseName)
}
if (this.expirationDB) {
- await this.expirationDB.close()
+ this.expirationDB.close()
this.expirationDB = null
}
function renderMedia (file: any, elem: HTMLVideoElement, opts: RenderMediaOptions, callback: (err: Error, renderer?: any) => void) {
const extension = extname(file.name).toLowerCase()
- let preparedElem: any = undefined
+ let preparedElem: any
let currentTime = 0
let renderer: any
if (!averageDownloadSpeed) averageDownloadSpeed = this.getAndSaveActualDownloadSpeed()
// Limit resolution according to player height
- const playerHeight = this.playerElement.offsetHeight as number
+ const playerHeight = this.playerElement.offsetHeight
// We take the first resolution just above the player height
// Example: player height is 530px, we want the 720p file instead of 480p
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
+// tslint:disable
import 'zone.js/dist/zone' // Included with Angular CLI.
/***************************************************************************************************
-export interface EventHandler<T> {
- (ev: T): void
-}
+export type EventHandler<T> = (ev: T) => void
export type PlayerEventType =
'pause' | 'play' |
private eventRegistrations: PlayerEventRegistrationMap = {}
public bindToChannel (channel: Channel.MessagingChannel) {
- for (let name of Object.keys(this.eventRegistrations)) {
+ for (const name of Object.keys(this.eventRegistrations)) {
channel.bind(name, (txn, params) => this.fire(name, params))
}
}
public registerTypes (names: string[]) {
- for (let name of names) {
+ for (const name of names) {
this.eventRegistrations[ name ] = { registrations: [] }
}
}
}
private constructChannel () {
- let channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope })
+ const channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope })
channel.bind('play', (txn, params) => this.embed.player.play())
channel.bind('pause', (txn, params) => this.embed.player.pause())
let currentState: 'playing' | 'paused' | 'unstarted' = 'unstarted'
setInterval(() => {
- let position = this.element.currentTime
- let volume = this.element.volume
+ const position = this.element.currentTime
+ const volume = this.element.volume
this.channel.notify({
method: 'playbackStatusUpdate',
}
private loadWebTorrentResolutions () {
- let resolutions = []
- let currentResolutionId = this.embed.player.webtorrent().getCurrentResolutionId()
+ const resolutions = []
+ const currentResolutionId = this.embed.player.webtorrent().getCurrentResolutionId()
for (const videoFile of this.embed.player.webtorrent().videoFiles) {
let label = videoFile.resolution.label
private loadParams () {
try {
- let params = new URL(window.location.toString()).searchParams
+ const params = new URL(window.location.toString()).searchParams
this.autoplay = this.getParamToggle(params, 'autoplay')
this.controls = this.getParamToggle(params, 'controls')
const lastPart = urlParts[ urlParts.length - 1 ]
const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
- let iframe = document.createElement('iframe')
+ const iframe = document.createElement('iframe')
iframe.src = `/videos/embed/${videoId}?autoplay=1&controls=0&api=1`
- let mainElement = document.querySelector('#host')
+ const mainElement = document.querySelector('#host')
mainElement.appendChild(iframe)
console.log(`Document finished loading.`)
- let player = new PeerTubePlayer(document.querySelector('iframe'))
+ const player = new PeerTubePlayer(document.querySelector('iframe'))
window[ 'player' ] = player
await player.ready
console.log(`Player is ready.`)
- let monitoredEvents = [
+ const monitoredEvents = [
'pause',
'play',
'playbackStatusUpdate',
let playbackRates: number[] = []
let currentRate = await player.getPlaybackRate()
- let updateRates = async () => {
- let rateListEl = document.querySelector('#rate-list')
+ const updateRates = async () => {
+ const rateListEl = document.querySelector('#rate-list')
rateListEl.innerHTML = ''
playbackRates.forEach(rate => {
if (currentRate === rate) {
- let itemEl = document.createElement('strong')
+ const itemEl = document.createElement('strong')
itemEl.innerText = `${rate} (active)`
itemEl.style.display = 'block'
rateListEl.appendChild(itemEl)
} else {
- let itemEl = document.createElement('a')
+ const itemEl = document.createElement('a')
itemEl.href = 'javascript:;'
itemEl.innerText = rate.toString()
itemEl.addEventListener('click', () => {
updateRates()
})
- let updateResolutions = ((resolutions: PeerTubeResolution[]) => {
- let resolutionListEl = document.querySelector('#resolution-list')
+ const updateResolutions = ((resolutions: PeerTubeResolution[]) => {
+ const resolutionListEl = document.querySelector('#resolution-list')
resolutionListEl.innerHTML = ''
resolutions.forEach(resolution => {
if (resolution.active) {
- let itemEl = document.createElement('strong')
+ const itemEl = document.createElement('strong')
itemEl.innerText = `${resolution.label} (active)`
itemEl.style.display = 'block'
resolutionListEl.appendChild(itemEl)
} else {
- let itemEl = document.createElement('a')
+ const itemEl = document.createElement('a')
itemEl.href = 'javascript:;'
itemEl.innerText = resolution.label
itemEl.addEventListener('click', () => {
"fullTemplateTypeCheck": true
},
"include": [
+ "./src",
"../../shared"
],
"exclude": [
{
- "extends": "tslint-config-standard",
- "rulesDirectory": ["./node_modules/codelyzer"],
+ "extends": [ "tslint-angular", "tslint-config-standard" ],
"rules": {
"no-inferrable-types": true,
"eofline": true,
"max-line-length": [true, 140],
"no-floating-promises": false,
"no-unused-variable": false, // Memory issues
+ "await-promise": [true, "PromiseLike"],
"member-ordering": [true, {
"order": [
"public-static-field",
]}
],
- "angular-whitespace": [true, "check-interpolation", "check-semicolon"],
- "banana-in-box": true,
- "templates-no-negated-async": true,
- "directive-selector": [true, "attribute", "my", "camelCase"],
- "component-selector": [true, "element", "my", "kebab-case"],
- "use-input-property-decorator": true,
- "use-output-property-decorator": true,
- "use-host-property-decorator": true,
- "use-view-encapsulation": true,
- "no-attribute-parameter-decorator": true,
- "no-input-rename": true,
- "no-output-rename": true,
- "no-output-on-prefix": true,
- "no-forward-ref": false,
- "use-life-cycle-interface": true,
- "contextual-life-cycle": true,
- "trackBy-function": false,
- "use-pipe-transform-interface": true,
- "pipe-prefix": [true, "my"],
- "component-class-suffix": true,
- "directive-class-suffix": true,
- "pipe-impure": true
+ "no-shadowed-variable": false,
+ "no-bitwise": false,
+ "max-classes-per-file": false,
+ "interface-over-type-literal": false
}
}
dependencies:
sprintf-js "~1.0.2"
-aria-query@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
- integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=
- dependencies:
- ast-types-flow "0.0.7"
- commander "^2.11.0"
-
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
-ast-types-flow@0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
- integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
-
ast-types@0.9.6:
version "0.9.6"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
-axobject-query@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9"
- integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==
- dependencies:
- ast-types-flow "0.0.7"
-
babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-codelyzer@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.0.0.tgz#e4032efb23a7c5d4bcfe7321fc1789490c679837"
- integrity sha512-Bif70XYt8NFf/Q9GPTxmC86OsBRfQZq1dBjdruJ5kZhJ8/jKhJL6MvCLKnYtSOG6Rhiv/44DU0cHk6GYthjy8Q==
+codelyzer@^4.0.2:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.5.0.tgz#a65ddeeeca2894653253a89bfa229118ff9f59b1"
+ integrity sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==
dependencies:
app-root-path "^2.1.0"
- aria-query "^3.0.0"
- axobject-query "^2.0.2"
- css-selector-tokenizer "^0.7.1"
+ css-selector-tokenizer "^0.7.0"
cssauron "^1.4.0"
- damerau-levenshtein "^1.0.4"
semver-dsl "^1.0.1"
source-map "^0.5.7"
- sprintf-js "^1.1.2"
+ sprintf-js "^1.1.1"
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
-commander@^2.11.0, commander@^2.12.1, commander@^2.18.0, commander@^2.19.0, commander@^2.9.0, commander@~2.19.0:
+commander@^2.12.1, commander@^2.18.0, commander@^2.19.0, commander@^2.9.0, commander@~2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
domutils "1.5.1"
nth-check "~1.0.1"
-css-selector-tokenizer@^0.7.1:
+css-selector-tokenizer@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d"
integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==
dependencies:
es5-ext "^0.10.9"
-damerau-levenshtein@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514"
- integrity sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=
-
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
dependencies:
through "2"
-sprintf-js@^1.1.2:
+sprintf-js@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
+tslint-angular@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/tslint-angular/-/tslint-angular-1.1.2.tgz#5ce7020968e3b9dc7a40b6d15dadd6da34787309"
+ integrity sha512-YDLdgQXBSFcVdDZH3mThx21fKzRctIgmCWpuwmppFLc7QHV3tdWDaFnD5lwUmgvLH8W0o+KsXhSzZ2uIsFJ+YA==
+ dependencies:
+ codelyzer "^4.0.2"
+ tslint "^5.8.0"
+
tslint-config-standard@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/tslint-config-standard/-/tslint-config-standard-8.0.1.tgz#e4dd3128e84b0e34b51990b68715a641f2b417e4"
tslib "1.9.0"
tsutils "^3.0.0"
-tslint@^5.7.0:
+tslint@^5.7.0, tslint@^5.8.0:
version "5.15.0"
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.15.0.tgz#6ffb180986d63afa1e531feb2a134dbf961e27d3"
integrity sha512-6bIEujKR21/3nyeoX2uBnE8s+tMXCQXhqMmaIPJpHmXJoBJPTLcI7/VHRtUwMhnLVdwLqqY3zmd8Dxqa5CVdJA==
*/
function getBaseBitrate (resolution: VideoResolution) {
switch (resolution) {
- case VideoResolution.H_240P:
- // quality according to Google Live Encoder: 300 - 700 Kbps
- // Quality according to YouTube Video Info: 186 Kbps
- return 250 * 1000
- case VideoResolution.H_360P:
- // quality according to Google Live Encoder: 400 - 1,000 Kbps
- // Quality according to YouTube Video Info: 480 Kbps
- return 500 * 1000
- case VideoResolution.H_480P:
- // quality according to Google Live Encoder: 500 - 2,000 Kbps
- // Quality according to YouTube Video Info: 879 Kbps
- return 900 * 1000
- case VideoResolution.H_720P:
- // quality according to Google Live Encoder: 1,500 - 4,000 Kbps
- // Quality according to YouTube Video Info: 1752 Kbps
- return 1750 * 1000
- case VideoResolution.H_1080P: // fallthrough
- default:
- // quality according to Google Live Encoder: 3000 - 6000 Kbps
- // Quality according to YouTube Video Info: 3277 Kbps
- return 3300 * 1000
+ case VideoResolution.H_240P:
+ // quality according to Google Live Encoder: 300 - 700 Kbps
+ // Quality according to YouTube Video Info: 186 Kbps
+ return 250 * 1000
+ case VideoResolution.H_360P:
+ // quality according to Google Live Encoder: 400 - 1,000 Kbps
+ // Quality according to YouTube Video Info: 480 Kbps
+ return 500 * 1000
+ case VideoResolution.H_480P:
+ // quality according to Google Live Encoder: 500 - 2,000 Kbps
+ // Quality according to YouTube Video Info: 879 Kbps
+ return 900 * 1000
+ case VideoResolution.H_720P:
+ // quality according to Google Live Encoder: 1,500 - 4,000 Kbps
+ // Quality according to YouTube Video Info: 1752 Kbps
+ return 1750 * 1000
+ case VideoResolution.H_1080P: // fallthrough
+ default:
+ // quality according to Google Live Encoder: 3000 - 6000 Kbps
+ // Quality according to YouTube Video Info: 3277 Kbps
+ return 3300 * 1000
}
}