Skip to content

Commit

Permalink
Update to ESM Module
Browse files Browse the repository at this point in the history
  • Loading branch information
donavanbecker committed Nov 3, 2024
1 parent 53178c1 commit 371d108
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 161 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/beta-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

if: ${{ github.repository == 'homebridge/camera-utils' }}

uses: homebridge/.github/.github/workflows/npm-publish.yml@latest
uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest
with:
tag: 'beta'
dynamically_adjust_version: true
Expand All @@ -40,4 +40,4 @@ jobs:
Version `v${{ needs.publish.outputs.NPM_VERSION }}`
url: "https://github.com/homebridge/camera-utils/releases/tag/v${{ needs.publish.outputs.NPM_VERSION }}"
secrets:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL_LATEST }}
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL_LATEST }}
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

if: ${{ github.repository == 'homebridge/camera-utils' }}

uses: homebridge/.github/.github/workflows/npm-publish.yml@latest
uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest
secrets:
npm_auth_token: ${{ secrets.npm_token }}

Expand All @@ -31,4 +31,4 @@ jobs:
Version `v${{ needs.publish.outputs.NPM_VERSION }}`
url: "https://github.com/homebridge/camera-utils/releases/tag/v${{ needs.publish.outputs.NPM_VERSION }}"
secrets:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL_LATEST }}
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL_LATEST }}
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [3.0.0](https://github.com/homebridge/camera-utils/compare/v2.2.7...v3.0.0) (2024-11-XX)
### [3.0.0](https://github.com/homebridge/camera-utils/compare/v2.2.7...v3.0.0) (2024-11-03)

### Other Changes
### Major Changes

* change to a esm module

### Other Changes

* update dependencies

### [2.2.7](https://github.com/homebridge/camera-utils/compare/v2.2.6...v2.2.7) (2024-11-03)
Expand Down
22 changes: 0 additions & 22 deletions build/github-releaser.js

This file was deleted.

1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 23 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
{
"name": "@homebridge/camera-utils",
"version": "3.0.0",
"type": "module",
"version": "2.3.0",
"description": "Utilities to simplify homebridge camera plugin development",
"author": "dgreif",
"maintainers": [
{
"name": "dgreif"
}
],
"license": "MIT",
"homepage": "https://github.com/homebridge/camera-utils#readme",
"repository": {
Expand All @@ -27,17 +22,19 @@
"rtp",
"ffmpeg"
],
"main": "lib/index.js",
"main": "dist/index.js",
"scripts": {
"check": "npm install && npm outdated",
"test": "vitest",
"test-coverage": "vitest run --coverage",
"watch:link": "npm link && tsc --watch --declaration",
"lint": "eslint '**/*.ts' --fix",
"build": "npm run clean && rm -rf lib && tsc --declaration",
"build": "npm run clean && tsc --declaration",
"prepublishOnly": "npm i --package-lock-only && npm run lint && npm run build",
"postpublish": "npm run clean",
"clean": "rimraf dist && rimraf coverage"
"clean": "rimraf dist && rimraf coverage",
"docs": "typedoc",
"lint-docs": "typedoc --emit none --treatWarningsAsErrors"
},
"standard-version": {
"scripts": {
Expand All @@ -47,30 +44,37 @@
"publishConfig": {
"access": "public"
},
"maintainers": [
"dgreif"
],
"dependencies": {
"execa": "^9.4.0",
"ffmpeg-for-homebridge": "^2.1.2",
"execa": "^9.5.1",
"ffmpeg-for-homebridge": "^2.1.7",
"pick-port": "^2.1.0",
"rxjs": "^7.8.1",
"systeminformation": "^5.23.5"
},
"files": [
"dist"
],
"devDependencies": {
"@antfu/eslint-config": "^3.7.3",
"@antfu/eslint-config": "^3.8.0",
"@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.7.4",
"@types/node": "^22.8.7",
"@types/semver": "^7.5.8",
"@types/source-map-support": "^0.5.10",
"@vitest/coverage-v8": "^2.1.2",
"@vitest/coverage-v8": "^2.1.4",
"dotenv": "^16.4.5",
"eslint": "^9.10.0",
"eslint": "^9.14.0",
"eslint-plugin-format": "^0.1.2",
"nodemon": "^3.1.7",
"rimraf": "^6.0.1",
"standard-version": "^9.5.0",
"ts-node": "^10.9.2",
"typescript": "^5.6.2",
"vite": "^5.4.8",
"vitest": "^2.1.2"
"typedoc": "^0.26.11",
"typescript": "^5.6.3",
"vite": "^5.4.10",
"vitest": "^2.1.4"
}
}
}
18 changes: 9 additions & 9 deletions src/default-ip.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import os from 'os'
import os from 'node:os'
import { networkInterfaceDefault } from 'systeminformation'

// NOTE: This is used to get the default ip address seen from outside the device.
// This _was_ needed to set the `address` field for hap camera streams, but the address is automatically determined after homebridge 1.1.3
// Keeping this here for backwards compatibility for now. All camera plugins will eventually drop support for <1.1.3 and this can be removed
export async function getDefaultIpAddress(preferIpv6 = false) {
const interfaces = os.networkInterfaces(),
defaultInterfaceName = await networkInterfaceDefault(),
defaultInterface = interfaces[defaultInterfaceName],
externalInfo = defaultInterface?.filter((info) => !info.internal),
preferredFamily = preferIpv6 ? 'IPv6' : 'IPv4',
addressInfo =
externalInfo?.find((info) => info.family === preferredFamily) ||
externalInfo?.[0]
const interfaces = os.networkInterfaces()
const defaultInterfaceName = await networkInterfaceDefault()
const defaultInterface = interfaces[defaultInterfaceName]
const externalInfo = defaultInterface?.filter(info => !info.internal)
const preferredFamily = preferIpv6 ? 'IPv6' : 'IPv4'
const addressInfo
= externalInfo?.find(info => info.family === preferredFamily)
|| externalInfo?.[0]

if (!addressInfo) {
throw new Error('Unable to get default network address')
Expand Down
56 changes: 33 additions & 23 deletions src/ffmpeg-process.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { spawn } from 'node:child_process'
import process from 'node:process'
import { Subject } from 'rxjs'
import { spawn } from 'child_process'
import { defaultFfmpegPath } from './ffmpeg'

const noop = () => null,
onGlobalProcessStopped = new Subject()
import { defaultFfmpegPath } from './ffmpeg.js'

// register a single event listener, rather than listener per ffmpeg process
// this helps avoid a warning for hitting too many listeners
const noop = () => null
const onGlobalProcessStopped = new Subject()

// Register a single event listener, rather than listener per ffmpeg process
// This helps avoid a warning for hitting too many listeners
process.on('exit', () => onGlobalProcessStopped.next(null))

export interface FfmpegProcessOptions {
Expand All @@ -23,31 +25,35 @@ export interface FfmpegProcessOptions {
}

export class FfmpegProcess {
private ff = spawn(
this.options.ffmpegPath || defaultFfmpegPath,
this.options.ffmpegArgs.map((x) => x.toString()),
)
private ff: ReturnType<typeof spawn>

private processSubscription = onGlobalProcessStopped.subscribe(() => {
this.stop()
})

private started = false
private stopped = false
private exited = false

constructor(public readonly options: FfmpegProcessOptions) {
const { logger, logLabel } = options,
logError = logger?.error || noop,
logInfo = logger?.info || noop,
logPrefix = logLabel ? `${logLabel}: ` : ''
this.ff = spawn(
this.options.ffmpegPath || defaultFfmpegPath,
this.options.ffmpegArgs.map(x => x.toString()),
)

if (options.stdoutCallback) {
const { logger, logLabel } = options
const logError = logger?.error || noop
const logInfo = logger?.info || noop
const logPrefix = logLabel ? `${logLabel}: ` : ''

if (options.stdoutCallback && this.ff.stdout) {
const { stdoutCallback } = options
this.ff.stdout.on('data', (data: any) => {
stdoutCallback(data)
})
}

this.ff.stderr.on('data', (data: any) => {
this.ff.stderr?.on('data', (data: any) => {
if (!this.started) {
this.started = true
options.startedCallback?.()
Expand All @@ -56,7 +62,7 @@ export class FfmpegProcess {
logInfo(logPrefix + data)
})

this.ff.stdin.on('error', (error) => {
this.ff.stdin?.on('error', (error) => {
if (!error.message.includes('EPIPE')) {
logError(logPrefix + error.message)
}
Expand All @@ -67,9 +73,9 @@ export class FfmpegProcess {
this.options.exitCallback?.(code, signal)

if (!code || code === 255) {
logInfo(logPrefix + 'stopped gracefully')
logInfo(`${logPrefix}stopped gracefully`)
} else {
logError(logPrefix + `exited with code ${code} and signal ${signal}`)
logError(`${logPrefix}exited with code ${code} and signal ${signal}`)
}
this.stop()
})
Expand All @@ -82,8 +88,8 @@ export class FfmpegProcess {
this.stopped = true
this.processSubscription.unsubscribe()

this.ff.stderr.pause()
this.ff.stdout.pause()
this.ff.stderr?.pause()
this.ff.stdout?.pause()

if (!this.exited) {
this.ff.kill()
Expand All @@ -95,7 +101,11 @@ export class FfmpegProcess {
return
}

this.ff.stdin.write(input)
this.ff.stdin.end()
if (this.ff.stdin) {
this.ff.stdin.write(input)
}
if (this.ff.stdin) {
this.ff.stdin.end()
}
}
}
16 changes: 8 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export * from './default-ip'
export * from './ffmpeg'
export * from './ffmpeg-process'
export * from './ports'
export * from './return-audio-transcoder'
export * from './rtp'
export * from './rtp-splitter'
export * from './srtp'
export * from './default-ip.js'
export * from './ffmpeg.js'
export * from './ffmpeg-process.js'
export * from './ports.js'
export * from './return-audio-transcoder.js'
export * from './rtp.js'
export * from './rtp-splitter.js'
export * from './srtp.js'
38 changes: 19 additions & 19 deletions src/ports.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Socket } from 'dgram'
import { AddressInfo } from 'net'
import type { Socket } from 'node:dgram'
import type { AddressInfo } from 'node:net'
import { pickPort } from 'pick-port'

// Need to reserve ports in sequence because ffmpeg uses the next port up by default. If it's taken, ffmpeg will error
Expand All @@ -17,27 +17,27 @@ export async function reservePorts({
}

const pickPortOptions = {
type,
reserveTimeout: 15, // 15 seconds is max setup time for HomeKit streams, so the port should be in use by then
}
const port = await pickPort(pickPortOptions)
const ports = [port]
const tryAgain = () => {
return reservePorts({
count,
type,
reserveTimeout: 15, // 15 seconds is max setup time for HomeKit streams, so the port should be in use by then
},
port = await pickPort(pickPortOptions),
ports = [port],
tryAgain = () => {
return reservePorts({
count,
type,
attemptNumber: attemptNumber + 1,
})
}
attemptNumber: attemptNumber + 1,
})
}

for (let i = 1; i < count; i++) {
try {
const targetConsecutivePort = port + i,
openPort = await pickPort({
...pickPortOptions,
minPort: targetConsecutivePort,
maxPort: targetConsecutivePort,
})
const targetConsecutivePort = port + i
const openPort = await pickPort({
...pickPortOptions,
minPort: targetConsecutivePort,
maxPort: targetConsecutivePort,
})

ports.push(openPort)
} catch (_) {
Expand Down
Loading

0 comments on commit 371d108

Please sign in to comment.