
Research
/Security News
npm Package Uses Prompt Injection and Token Flooding to Disrupt AI Malware Scanners
A new npm package tests AI malware scanners with prompt injection, safety-triggering comments, context flooding, and obfuscated JavaScript.
@nrk/player-elements
Advanced tools
Headless building blocks for creating a web players handling NRK content.
The elements in this package uses attributes for configuration and specifically the type attribute is used for some automagic, specifically to find the player element in the dom. All elements inherit from @nrkno/reactive-element (https://github.com/nrkno/web-custom-elements/tree/master/packages/reactive-element) to handle updates and react to changes in the dom.
An important concept in player-elements is also shadowed properties. You can specify properties in an element that shadows the same properties in another element, and you will get updates when they are updated in the element you are shadowing. For instance, in the volume controller it shadows muted and volume from player. When some button triggers the PlayerActions.toggleMute action, the property muted is toggled in the player instance. Since muted is shadowed in the VolumeElement class, it is changed there also. Shadowing is handled in the @nrkno/element-shadow-properties-mixin package from @nrk/web-custom-elements.
Elements have default styles in the release, based on a dash-type suffix.
These styles exists for the following elements:
-player-controls-poster-scrubber-volume-subtitlesThe point here is that if you create a plain player inheriting from PlayerElement and give it the -player class, you get the default player look and the same applies for all other elements. But you are of course free to both change the HTML of the elements and the css, for customising the look and feel. A good approach can be to use both -player class and your own classes to use the base css and extend it.
In addition there are some helper classes for positioning and reset. Important helper classes are for controlling player aspect ratio. The following classes can do that (from helper classes)
.aspect-ratio--235x1.aspect-ratio--4x3.aspect-ratio--1x1.aspect-ratio--2x3.aspect-ratio--9x16.aspect-ratio--16x9The player element (class PlayerElement) is the central custom element used for creating a player. Without it, you would not have a player at all. The player element use player-core internally for handling playback and sends commands to a player core session when the user uses the player. As other elements in this package, it is configured via html attributes.
Supported attributes are (attribute names in HTML must be lowercase):
| Name | Data type | Required | Description |
|---|---|---|---|
| src | string | yes | The media source to play. See below for format spec |
| autoplay | boolean | no | Start to play media (if the browser allows it) |
| blockedcontentage | number | no | Age restriction. Content rated with this value or higher will be blocked and error thrown |
| muted | boolean | no | Mute audio or not |
| aidiagnosticsid | string | no | id sent with all application insigth events |
| loop | boolean | no | Loop playback |
| starttime | number | Date | no | Start playback at time specified, in seconds for on-demand streams or a Date inside the stream for live streams. |
| volume | number | no | Volume level 0-1.0 |
| user | Object | no | A UserState object representing a logged in user |
| preferredmanifest | string | no | The preferred manifest is either synstolk, tegntolk, all-speech-subtitles or default |
| preferredsubtitle | string | no | Either none for no subtitles or string representing the subtitle label |
| preferredbandwith | string | no | Preferred bandwith use for streaming. One of "low" | "mid" | "high" | "auto" | "highest" |
| playbackrate | number | no | The rate of playback, 1.0 is normal playback, 0.5 is 50% speed, 1.5 is 1.5x speed |
| psapiorigin | string | no | baseUrl for psapi |
| psapirecommendationsorigin | string | no | baseUrl for psapi recommendations |
| npawaccountcode | string | no | account name for NPAW tracking. No tracking is done without it |
| snowplowurl | string | no | Required for enabling snowplow tracking. collector Url for snowplow tracking |
| snowplowappid | string | no | Required for enabling snowplow tracking. appId for snowplow tracking, see https://github.com/nrkno/snowplow-tooling |
| snowplowserviceid | string | no | serviceid for snowplow tracking, see Service schema for valid values |
| snowplowos | string | no | Operating systems name as a string to use for snowplow tracking |
| cdnoverride | string | no | Override psapi calls to only use this cdn. One of {akamai, globalconnect, telenor} |
| features | Array | no | Serialized list of feature toggle keys for the player |
| availablechannelids | Array | no | List of channel ids that are available to the current user |
Subclasses of this element must implement their version of the method initPlayerCoreInstance() since they are responsible for loading the player-core lib, often done dynamically. The method should set the PlayerCore instance on the property this.player.
The PlayerCore constructor must have the this element and a list of configured adapters as parameters and an optional configuration object. See https://static.nrk.no/player-core/latest/docs/classes/core_player_core.PlayerCore.html#constructor for details. Most noteworthy is the crossOrigin setting on mediaElementOptions which must be set to anonymous if subtitles will be loaded from https://undertekst.nrk.no, which is the most common case for NRK players. PlayerCore default value for this setting is none due to technical limitations in the Telenor CDN configuration regarding accept-ranges requests and cors headers.
The src attribute has multiple modes depending on what you want to play. It has three parts
[scheme]:[type]:id
Scheme can only be nrk at present, and the scheme and type part is not optional. Type can be either program, channel or clip. A program type will expect id to be a PRF program if for use with PSAPI, channel expects id to be a psapi channel id (nrk1, nrk2 etc) while clip will expect id to be a Potion clip id. The lookup of manifest and metadata for nrk content is handled by the player-psapi-client package. Examples:
nrk:channel:nrk1nrk:program:MSUS08000119nrk:clip:79d1a9e9-48cd-4e2f-869c-b0b0bbaec0benrk:clip:261025If starttime is unset or undefined, an on-demand stream will start at the beginning (time=0) while a live stream will start at the "now" time. If one wants to start playback at another position in the stream, startTime (on-demand) or startTimeLive (live streams) must be set. An on-demand stream always starts at 0, so startTime is seconds from start. A live stream does not, and it will have timestamps for start and end internally after loading. Therefore, startTimeLive is a timestamp (Date) specifying when to start the playback within the live stream.
The PlayerElement uses player-psapi-client to load data from psapi for the src specified, in two separate calls for metadata and manifest data. Both are available as reactive properties on player for other elements to shadow or access.
See documentation for the metadata and manifest endpoints on PSAPI playback docs and there is typescript api doc for Manifest and Metadata interfaces.
The player element has a non-exported method fakeError(type: string | PlaybackErrorTypes, fatal?: boolean) method which can be handy for test, debug and development.
When the player-element is selected in browser development console one can call the following in the browser console:
$0.fakeError('CHANNEL_GEOBLOCK_ERROR');
The make the player emit that error as a PlayerError event, for context listening for that event (smart-tv-player tizen app is one such context). Call the method without any arguments to get an unspecified error and usage information for the method in the console.
The poster-element (class PosterElement) is an element used for showing content to the user before playback starts, typically the key art for the content loaded, a play button, age limit and other elements. The poster is hidden when playback starts. When the poster is added to a parent player, it shadows some data from the player, which is useful. When metadata is fetched in the player, the poster gets it too, so we can display it there. This metadata is:
The last three properties are only specified if available is false.
It sets a accessibleDescription text based on these metadata and picks the image matching the player dimensions which is set as src. If you set the src on poster itself, that takes presedence over the choosing logic for the image src. The poster should also take care of showing end user messages (included in availability) from PSApi when the src is non-playable due to normal circumstances like content no longer available, not yet started, geoblocked etc.
The controls element (class ControlsElement) is a container for other controls in the player, handling various states and events for the player. Default is that click in the controls element not hitting a specific control toggles playback. The controls element is hidden before playback starts and visible afterwards (just as poster is visible before playback and hidden afterwards). Normally the controls element itself is invisible, but the controls inside are shown when appropriate.
The keyboard element handles all keyboard navigation like seeking, muting, toggling playback and more, and is and should be headless. Add this to your player, and it will handle your keyboard navigation needs. Override it and implement your own if you need.
| Key | Action |
|---|---|
| Space | toggle playback |
| Enter | toggle playback |
| Arrow left | seek back by default seekable step in player. |
| Arrow right | seek forward by default seekable step in player. |
| Arrow up | Increase volume 10% |
| Arrow down | Decrease volume 10% |
| 0-9 | jump in time, 0%, 10%, 20%, 30% into stream etc. |
| Home | jump to start |
| End | Jump to end |
| K | Start playback |
| M | Toggle mute |
| J | Seek back, same as arrow |
| L | Seek forward, same as arrow |
| F | Toggle full screen mode (WIP) |
| P | Toggle player in player mode (WIP) |
Also, if a modifier key (ctrl, shift, alt or meta) is pressed while seeking, the seek distance is 5x as big. The base seek step is calculated based on the range of the stream, but never less than 1 second.
The scrubber (class ScrubberElement) is the element showing the user where they are in the stream, and how much time has passed and remains. It is letting them use touch or mouse to navigate the stream. The scrubber element default class -scrubber has some sensible default styles for a basic scrubber and uses two variables --player-playhead-height and --player-progressbar-height for many calculations. These can be overriden in your bundle to customise the look of the scrubber.
The ScrubberElement class expects to find HTML elements of several types to function. The scrubber responds to a lot of interaction and dispatches events to the player. These types are
Example markup
<input
autofocus
class="reset-input-range"
action="${PlayerActions.SeekTo}"
action:events="click,change"
type="range"
min="0"
max="100"
step="1"
aria-label="Spol"
/>
<div type="progressbar" aria-hidden="true">
<div type="playhead"></div>
<div type="progressbar-full"></div>
<div type="progressbar-played"></div>
</div>
<div type="start-time" aria-hidden="true"></div>
<div type="end-time" aria-hidden="true"></div>
<div type="playhead-time" aria-hidden="true"></div>
<div type="pointer-time" aria-hidden="true"></div>
The volume element (class VolumeElement) is a volume controller handling volume adjustments and muting/unmuting. The base class handles volume level and muting/unmuting but can look the way you want, the only css on the -volume class is display: block, everything else is up to you. Example markup:
<button action="${PlayerActions.ToggleMute}" type="mute-button" aria-label="${this.muted ? 'Lyd på' : 'Lyd av'}">
<svg></svg>
</button>
<div class="volume-control absolute top left">
<input
class="absolute reset-input-range"
action="${PlayerActions.SetVolume}"
type="range"
min="0"
max="1"
step="0.1"
aria-label="Juster lydnivå"
.value="${this.volume}"
/>
<div class="slider absolute" aria-hidden="true">
<div class="slider-fill" style="width: ${sliderProgress}%;"></div>
<div class="slider-thumb-track">
<div class="absolute slider-thumb" style="left: ${sliderProgress}%;"></div>
</div>
</div>
</div>
The volume controller shadow the mute and volume properties from the player.
The tracker is element taking care of all tracking of playback.
For snowplow tracking attributes snowplowappid and snowplowurl and possibly snowplowserviceid needs to be set.
See table of attributes for the player-element for more info.
See player-tracker
Subtitles are handled by PlaybackStateMixin and SubtitleElement in combination. All state regarding subtitles is represented in the SubtitleState object on the Player element, set up by PlaybackStateMixin, but rendering is handled by extending the generic SubtitleElement and listening on update events for SubtitleState and rendering activeCues when they change. SubtitleElement also handles speaking the subtitle text, through the PlayerActions.Speak action.
SubtitleElement also has methods for parsing webVTT formatting and applying classes to it, but this can be overridden when needed.
Subtitles has default styles on the -subtitles class. A suitable HTML structure for subtitles using these styles should be
<player-subtitle-element class="-subtitles" type="subtitles">
<div class="subtitles__line">
<span class="subtitle__text">Subtitle text</span>
</div>
</player-subtitle-element>
FAQs
Unknown package
The npm package @nrk/player-elements receives a total of 0 weekly downloads. As such, @nrk/player-elements popularity was classified as not popular.
We found that @nrk/player-elements demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 200 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A new npm package tests AI malware scanners with prompt injection, safety-triggering comments, context flooding, and obfuscated JavaScript.

Product
Socket now detects supply chain risks in project manifests, starting with missing lockfiles that can make dependency installs non-reproducible.

Research
/Security News
The trojanized extensions use TinyGo-compiled WebAssembly and Solana transaction memos to resolve command-and-control infrastructure.