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

media-devices-util

v0.2.0

Published

This package exposes and API to work with mac/win media devices (cameras, microphones, screens)

Downloads

41

Readme

media-devices-util

What is this package for? To get info about available media devices and work with them. You can:

  • list available devices
  • get default devices
  • get audio/video/screen permissions (mac)
  • request for audio/video/screen permissions (mac)

How to use it

Install

npm i -S media-devices-util

Use

Get devices list

const mediaDevicesUtil = require("media-devices-util");

const videoDevices = mediaDevicesUtil.getVideoDevices();
const audioDevices = mediaDevicesUtil.getAudioDevices();

console.log({ audioDevices, videoDevices });

// output on mac:
// {
//     audioDevices: [
//         {
//             id: 'AppleHDAEngineInput:1F,3,0,1,0:1',
//             label: 'Built-in Microphone'
//         }
//     ],
//     videoDevices: [
//         {
//             id: '0x1420000005ac8600',
//             label: 'FaceTime HD Camera (Built-in)'
//         },
//         {
//             id: '69733382',
//             label: 'Capture screen 0'
//         }
//     ]
// }
//
// output on windows:
// {
//     audioDevices: [
//         {
//             id: '0',
//             label: 'Microphone (High Definition Audio Device)',
//             alternativeName: '@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\\wave_{B073E9D3-C0A7-4CB0-84E0-F829B281F95F}'
//         }
//     ],
//     videoDevices: [
//         {
//             id: '\\\\?\\usb#vid_203a&pid_fff9&mi_00#6&fafa70b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\global',
//             label: 'FaceTime HD Camera (Built-in)'',
//             alternativeName: '@device_pnp_\\\\?\\usb#vid_203a&pid_fff9&mi_00#6&fafa70b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\global'
//         }
//     ]
// }

Request for Camera permissions

const mediaDevicesUtil = require("media-devices-util");

mediaDevicesUtil.requestMediaAuthorization("camera").then((status) => {
  if ("AUTHORIZED" === status) {
    // permissions granted!
  }
});

API

media-devices-util object has the following API:

type TDevice = {
  // For mac:
  // audio/video devices are using the 'uniqueID' property - https://developer.apple.com/documentation/avfoundation/avcapturedevice/1390477-uniqueid
  // screen devices are using the 'CGDirectDisplayID' property - https://developer.apple.com/documentation/coregraphics/cgdirectdisplayid
  // For win:
  // audio devices are using the 'WaveInID' property - https://docs.microsoft.com/en-us/windows/win32/directshow/selecting-a-capture-device
  // video devices are using the 'DevicePath' property - https://docs.microsoft.com/en-us/windows/win32/directshow/selecting-a-capture-device
  id: string;

  // For mac:
  // audio/video devices are using the 'localizedName' property - https://developer.apple.com/documentation/avfoundation/avcapturedevice/1388222-localizedname
  // screen devices are using the 'Capture screen ' prefix plus device id in 'CGGetActiveDisplayList' - https://developer.apple.com/documentation/coregraphics/1454603-cggetactivedisplaylist
  // For win:
  // using the 'FriendlyName' property - https://docs.microsoft.com/en-us/windows/win32/directshow/selecting-a-capture-device
  label: string;

  // For win:
  // using the 'GetDisplayName' method's return value - https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imoniker-getdisplayname
  alternativeName?: string;
}

// AUTHORIZED - permissions granted
// DENIED - permissions denied
// NOT_DETERMINED - permissions not set
declare type TAuthorization = "AUTHORIZED" | "DENIED" | "NOT_DETERMINED";

declare type TMediaType = "camera" | "microphone";

type TMediaDevicesUtil = {
    getDefaultVideoDevice(): TDevice;
    getDefaultAudioDevice(): TDevice;
    getVideoDevices(): TDevice[];
    getAudioDevices(): TDevice[];
    getScreenAuthorizationStatus(): TAuthorization;
    getMediaAuthorizationStatus(mediaType: TMediaType): TAuthorization;
    getMediaAuthorizationStatus(): {
        camera: TAuthorization;
        microphone: TAuthorization;
    };
    requestScreenAuthorization(): TAuthorization;
    requestMediaAuthorization(mediaType: TMediaType): Promise<TAuthorization>;
}

getDefaultVideoDevice

Return type: TDevice

Retrieve the default video input device (camera).

For win, taking the first entry of the IEnumMoniker with the CLSID_VideoInputDeviceCategory parameter.

For mac, using the defaultDeviceWithMediaType:AVMediaTypeVideo method for audio/video devices.

getDefaultAudioDevice

Return type: TDevice

Retrieve the default audio input device (microphone).

For win, using the GetDefaultAudioEndpoint method.

For mac, using the defaultDeviceWithMediaType:AVMediaTypeAudio method.

getVideoDevices

Return type: TDevice[]

Retrieve the default video input devices list (cameras, screens, etc.).

For mac, using the devicesWithMediaType:AVMediaTypeVideo method, and the CGGetActiveDisplayList method for screens.

For win, using the IEnumMoniker with the CLSID_VideoInputDeviceCategory parameter.

getAudioDevices

Return type: TDevice[]

Retrieve the default audio input devices list (microphones, virtual devices, etc.).

For mac, using the devicesWithMediaType:AVMediaTypeAudio method.

For win, using the IEnumMoniker with the CLSID_AudioInputDeviceCategory parameter.

getScreenAuthorizationStatus

Return type: TAuthorization

Retrieve current permissions for screen recording.

For mac, using the CGPreflightScreenCaptureAccess method (>=11.0), or will try to match window processes ids (>=10.15), or will return AUTHORIZED.

For win, will always return AUTHORIZED.

getMediaAuthorizationStatus

Return type: TAuthorization | { camera: TAuthorization; microphone: TAuthorization; }

Arguments: (mediaType?: TMediaType)

Retrieve current permissions for audio and/or video usage. If no args passed - will return authorization status for both audio/video.

For mac, using the authorizationStatusForMediaType method.

For win, will always return AUTHORIZED for any type of media.

requestScreenAuthorization

Return type: TAuthorization

Request for screen recording permissions. Will prompt user to modify screen recording permissions config, if possible, otherwise - will open the System Preferences window with Screen Recording tab opened.

For mac, using the CGRequestScreenCaptureAccess method (>=11.0), or will try to use CGDisplayStreamCreate method (>=10.15), or will return AUTHORIZED.

For win, will always return AUTHORIZED.

requestMediaAuthorization

Return type: Promise<TAuthorization>

Arguments: (mediaType: TMediaType)

Request for microphone or camera recording permissions. Will prompt user to modify screen recording permissions config, if possible, otherwise - will open the System Preferences window with Camera or Microphone tab opened.

For mac, using the requestAccessForMediaType method (>=10.14), or will return AUTHORIZED.

For win, will always return AUTHORIZED for any type of media.

FFMPEG

When using an ffmpeg or other libs to capture audio/video devices, you first need to obtain a list of available devices and their labels (IDs).

And when running ffmpeg to just get the devices list - it takes too long, because a lot of overhead ffmpeg lib actions are taken.

Using media-devices-util is much, much faster.

Usage example

Let's imagine, that we want to capture the default audio and default video device with ffmpeg:

const spawn = require("child_process").spawn;
const mediaDevicesUtil = require("media-devices-util");

const defaultVideoDevice = mediaDevicesUtil.getDefaultVideoDevice();
const defaultAudioDevice = mediaDevicesUtil.getDefaultAudioDevice();

// for MacOS, you can use the 'label' prop, and the item's index (if used with getVideoDevices/getAudioDevices):
const ffmpegWinProcess = spawn("ffmpeg", ["-f", "avfoundation", "-i", `${defaultVideoDevice.label}:${defaultAudioDevice.label}`, "video.mkv"]);

// for Windows, you should use the 'label' or the 'alternativeName' prop:
const ffmpegMacProcess = spawn("ffmpeg", ["-f", "dshow", "-i", `video="${defaultVideoDevice.label}":audio="${defaultAudioDevice.alternativeName}"`, "video.mkv"]);

Alternatives

You can use the ffmpeg's list_devices option (for mac or win), and parse it's output to get the list itself.

Also, you can use other ffmpeg command abstractions (like ffmpeg and fluent-ffmpeg).

In any case, the list_devices in ffmpeg lib is something like a crunch, and the lib itself doesn't provide a programmatic way to enumerate devices.

Or use other ffmpeg nodejs bindings lib.

Next Steps

  • Improve Windows API (especially permissions), if possible
  • Add listeners for devices and/or permissions

License

MIT License