UNPKG

bitmovin-player-ui

Version:
135 lines (114 loc) 4.68 kB
import { PlayerAPI, SegmentPlaybackEvent, VideoQuality } from 'bitmovin-player'; import { i18n } from '../localization/i18n'; import { Container, ContainerConfig } from './Container'; import { EcoModeToggleButton } from './buttons/EcoModeToggleButton'; import { Label, LabelConfig } from './labels/Label'; import { SettingsPanelItem, SettingsPanelItemConfig } from './settings/SettingsPanelItem'; /** * @category Containers */ export class EcoModeContainer extends Container<ContainerConfig> { private ecoModeSavedEmissionsItem: SettingsPanelItem<SettingsPanelItemConfig>; private ecoModeToggleButtonItem: SettingsPanelItem<SettingsPanelItemConfig>; private emissionsSavedLabel: Label<LabelConfig>; private savedEmissons = 0; private currentEnergyEmission: number; constructor(config: ContainerConfig = {}) { super(config); const ecoModeToggleButton = new EcoModeToggleButton(); const labelEcoMode = new Label({ text: i18n.getLocalizer('ecoMode.title'), for: ecoModeToggleButton.getConfig().id, id: 'ecomodelabel', }); this.emissionsSavedLabel = new Label({ text: `${this.savedEmissons.toFixed(4)} gCO2`, cssClass: 'ui-label-savedEnergy', }); this.ecoModeToggleButtonItem = new SettingsPanelItem({ label: labelEcoMode, settingComponent: ecoModeToggleButton, }); this.ecoModeSavedEmissionsItem = new SettingsPanelItem({ label: 'Saved Emissions', settingComponent: this.emissionsSavedLabel, hidden: true, }); this.addComponent(this.ecoModeToggleButtonItem); this.addComponent(this.ecoModeSavedEmissionsItem); ecoModeToggleButton.onToggleOn.subscribe(() => { this.ecoModeSavedEmissionsItem.show(); this.onToggleCallback(); }); ecoModeToggleButton.onToggleOff.subscribe(() => { this.ecoModeSavedEmissionsItem.hide(); this.onToggleCallback(); }); } private onToggleCallback: () => void; public setOnToggleCallback(callback: () => void) { this.onToggleCallback = callback; } configure(player: PlayerAPI): void { player.on(player.exports.PlayerEvent.SegmentPlayback, (segment: SegmentPlaybackEvent) => { if (!segment.mimeType.includes('video')) { return; } const { height, width, bitrate, frameRate } = segment.mediaInfo; const { height: maxHeight, bitrate: maxBitrate, width: maxWidth, } = this.getMaxQualityAvailable(player.getAvailableVideoQualities()); const currentEnergyKwh = this.calculateEnergyConsumption(frameRate, height, width, bitrate, segment.duration); const maxEnergyKwh = this.calculateEnergyConsumption( frameRate, maxHeight, maxWidth, maxBitrate, segment.duration, ); if (this.ecoModeSavedEmissionsItem.isShown()) { this.updateSavedEmissions(currentEnergyKwh, maxEnergyKwh, this.emissionsSavedLabel); } }); } updateSavedEmissions( currentEnergyConsuption: number, maxEnergyConsuption: number, emissionsSavedLabel: Label<LabelConfig>, ) { // 475 is the average carbon intensity of all countries in gCO2/kWh const averageCarbonIntensity = 475; this.currentEnergyEmission = currentEnergyConsuption * averageCarbonIntensity; const maxEnergyEmisson = maxEnergyConsuption * averageCarbonIntensity; this.savedEmissons += maxEnergyEmisson - this.currentEnergyEmission; emissionsSavedLabel.setText(this.savedEmissons.toFixed(4) + ' gCO2'); } /** * The calculations are based on the following paper: https://arxiv.org/pdf/2210.05444.pdf */ calculateEnergyConsumption(fps: number, height: number, width: number, bitrate: number, duration: number): number { const fpsWeight = 0.035; const pixeldWeight = 5.76e-9; const birateWeight = 6.97e-6; const constantOffset = 8.52; const bitrateInternetWeight = 3.24e-5; const internetConnectionOffset = 1.15; const videoCodec = 4.16; const energyConsumptionW = fpsWeight * fps + pixeldWeight * height * width + (birateWeight + bitrateInternetWeight) * (bitrate / 1000) + videoCodec + constantOffset + internetConnectionOffset; // Convert energy consumption from Watts (W) to Kilowatt-hours (kWh) for the given time duration of the segment const energyConsumptionKwh = (energyConsumptionW * duration) / 3.6e6; return energyConsumptionKwh; } getMaxQualityAvailable(availableVideoQualities: VideoQuality[]) { const sortedQualities = availableVideoQualities.sort((a, b) => a.bitrate - b.bitrate); return sortedQualities[sortedQualities.length - 1]; } }