npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

omxconductor

v2.4.0

Published

Orchestrate omxplayer instances via NodeJS

Downloads

29

Readme

OMX Conductor

A convenient library for initiating and controlling video playback on omxplayer -- the command-line OpenMAX media player built especially for Raspberry Pi -- via NodeJS.

Check your GPU memory!

If you intend to play more than 1 video simultaneously, you should make sure that your Raspberry Pi is configured with more than the default 64MB normally allocated to the GPU. Otherwise you will get strange crashes.

To do it:

sudo raspi-config

...then pick 4 Performance Options, then P2 GPU Memory and type a new value (128MB is good enough for 2 layers).

Reboot the machine.

Use in your client application

Install

npm install omxconductor

Include the Player

const Player = require('omxconductor')

Instantiate the Player with media (file path or network stream) and optional settings (an object)

const player = new Player('media/bigbuckbunny.mp4', { loop: true })

Open the video and start playback. open() returns a Promise so you can also handle the result of successfully (or not) opening the video:

player
  .open()
  .then((result) => {
    console.log('Clip started playing OK! Some information:', result)
  })
  .catch((err) => {
    console.error('error on open:', err)
  })

See a working example in the ./demo/demo.js file.

Omxplayer instance configuration

The API provides some options which are converted into suitable omxplayer arguments, as well as sensible defaults. You provide these as key/value pairs in the options object when calling new Player

The most common ones are shown below:

  layer: number;
  backgroundColor: string;
  loop: boolean;
  initVolume: number;
  orientation: number;
  subtitlesPath?: string;
  otherOmxFlags?: string;

The last one - otherOmxFlags - allows you to pass whatever additional omxplayer flags you need, as per https://github.com/popcornmix/omxplayer#synopsis

So for example, if you wanted to pass a font size for subtitles, and also set an alpha value, you could append these options as follows:

const player = new Player('somevideo.mp4', { otherOmxFlags: '--alpha 100 --font-size 40'})

Hook into events during playback

The Player class extends the NodeJS EventEmitter class, so you can register your own listener functions. For example:

player.on('open', (result) => {
  console.log('open event:', result)
})

The list of available events so far, and a description of their meaning:

  • open: Emitted when the video clip is successfully opened by omxplayer. A result object is included with the call to the listener, with some details about the clip that was open.
  • ready: Emitted when omxconductor has successfully connected to the running omxplayer instance via D-Bus. You should wait for this event before trying to do any live control of the video from your application. A result object includes some information including how many attempts it took before the instance was connected.
  • progress: Emitted repeatedly (by default, about 60 times per second!) as the clip plays. You get an object with the properties position, duration and progress which is simply position / duration (i.e. 0 is the beginning, 0.5 is halfway and 1.0 is the end).
  • error: Emitted on any kind of error in opening, playback, control commands, etc. An error object includes some (hopefully) useful information about what went wrong.
  • stopped: Emitted when playback was successfully stopped manually (i.e. by your client application). Expect to receive a closed event immediately after this, because stopping playback closes the omxplayer instance.
  • paused: Emitted when playback was successfully paused
  • resumed: Emitted when playback was successfully resumed (paused => playing)
  • close: Emitted when the omxplayer instance stops and/or the pipe closes. This could be good or bad, depending on the scenario. The result object returned includes the properties err, stdout, stderr which you can use to figure out what happened.

Control the player while it's running

This is where the real power comes in. You can tell the player to seek, pause, etc. while it's running, via your client application.

All of the functions below are async (use Promises). For example:

await player.seekAbsolute(1000);
console.log('we just jumped to the 1 second mark!');

Here is a list of the available functions (so far); more coming soon...

  • seekAbsolute = (positionMs: number): jump to the position in the clip (specified in milliseconds)
  • pause = (): pause playback (omxplayer instance is still running and progress will still be updated)
  • resume = (): resume playback if paused (has no effect if already playing)
  • stop = (): stop playback (omxplayer instance will actually quit, but no errors should be thrown)

Registering triggers

You can register handler functions that are triggered at specific positions (specified in milliseconds). The system continuously checks the progress of the player and tries to call the handler as close as possible to the position you specified. The handler is guarranteed to only be called once - at least until the playhead moves to a position before the trigger point (in which case it is flagged to become triggerable again).

Here is an example where the system will jump to position 0 whenever it hits position 6000 (6 seconds in):

player.registerPositionTrigger(6000, (actualPosition) => {
      console.log('hit 6000ms trigger @', actualPosition)
      player.seekAbsolute(0)
    })

If for some reason you need another mode of control, you can also a listener on progress events and implement your own logic. For example:

player.on('progress', (progress) => {
  console.log('progress event:', progress)
  if (progress.progress >= 0.2) {
    console.log('pause...')
    player.pause()
  }
})

A note on seek accuracy

If you are playing common formats such as H.264 and H.265 (recommended) then you might find that seeking to positions other than zero (0ms) is unreliable. This is because of Inter-frame compression used in these codecs. If you need more accurate seek points, you will need to trans/en-code your video with keyframes explicitly set at these points.


Development

Testing clients against local (linked) version

You need to run npm link in the dist folder (after building).

Quick build

If you are testing on a Raspberry Pi and need a quick(er) build (no linting, no tests, etc.), run:

npm run quickbuild

Background

A successor to https://github.com/anselanza/omx-layers

We control the omxplayer instance(s) after launch using D-Bus, a message bus system that allows for communication between applications.