homekit: ffmpeg encoder suggestions

This commit is contained in:
Koushik Dutta
2021-10-14 23:26:18 -07:00
parent 4503a8da20
commit a64cb494a2
4 changed files with 147 additions and 4 deletions

View File

@@ -0,0 +1,124 @@
import os from 'os';
import fs from 'fs';
import { CodeActionCommand } from 'typescript';
const PI_MODEL_NO = [
// https://www.raspberrypi.org/documentation/hardware/raspberrypi/
'BCM2708',
'BCM2709',
'BCM2710',
'BCM2835', // Raspberry Pi 1 and Zero
'BCM2836', // Raspberry Pi 2
'BCM2837', // Raspberry Pi 3 (and later Raspberry Pi 2)
'BCM2837B0', // Raspberry Pi 3B+ and 3A+
'BCM2711' // Raspberry Pi 4B
];
function isPi(model: string) {
return PI_MODEL_NO.indexOf(model) > -1;
}
export function isRaspberryPi() {
let cpuInfo: string;
try {
cpuInfo = require('realfs').readFileSync('/proc/cpuinfo', { encoding: 'utf8' });
}
catch (e) {
// if this fails, this is probably not a pi
return false;
}
const model = cpuInfo
.split('\n')
.map(line => line.replace(/\t/g, ''))
.filter(line => line.length > 0)
.map(line => line.split(':'))
.map(pair => pair.map(entry => entry.trim()))
.filter(pair => pair[0] === 'Hardware')
if (!model || model.length == 0) {
return false;
}
const number = model[0][1];
return isPi(number);
}
export type CodecArgs = { [type: string]: string[] };
export function getH264DecoderArgs(): CodecArgs {
if (isRaspberryPi()) {
return {
'Raspberry Pi': ['-c:v', 'h264_mmal'],
'Video4Linux': ['-c:v', 'h264_v4l2m2m'],
}
}
else if (os.platform() === 'darwin') {
return {
'VideoToolbox': ['-hwaccel', 'videotoolbox']
}
}
const ret: CodecArgs = {
'Nvidia CUDA': [
'-vsync', '0', 'hwaccel', 'cuda', '-hwaccel_output_format', 'cuda',
],
'Nvidia CUVID:': [
'-vsync', '0', 'hwaccel', 'cuvid', '-c:v', 'h264_cuvid',
],
};
if (os.platform() === 'linux') {
ret['Video4Linux'] = [
'-c:v', 'h264_v4l2m2m',
];
ret['']
}
else if (os.platform() === 'win32') {
ret['Intel QuickSync'] = [
'-c:v', 'h264_qsv',
];
}
else {
return {};
}
return ret;
}
export function getH264EncoderArgs() {
const encoders: { [type: string]: string } = {};
if (isRaspberryPi()) {
encoders['Raspberry Pi'] = 'h264_omx';
encoders['Video4Linux'] = 'h264_v4l2m2m';
}
else if (os.platform() === 'darwin') {
encoders['VideoToolbox'] = 'h264_videotoolbox';
}
else if (os.platform() === 'win32') {
// h264_amf h264_nvenc h264_qsv
encoders['Intel QuickSync'] = 'h264_qsv';
encoders['AMD'] = 'h264_amf';
encoders['Nvidia'] = 'h264_nvenc';
}
else if (os.platform() === 'linux') {
// h264_v4l2m2m h264_vaapi nvenc_h264
encoders['Video4Linux'] = 'h264_v4l2m2m';
encoders['VAAPI'] = 'h264_vaapi';
encoders['Nvidia'] = 'nvenc_h264';
}
else {
return {};
}
const encoderArgs: CodecArgs = {};
for (const [name, encoder] of Object.entries(encoders)) {
encoderArgs[name] = [
'-c:v',
encoder,
'-b:v',
'${request.video.max_bit_rate * 10}k',
]
}
return encoderArgs;
}

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/homekit",
"version": "0.0.83",
"version": "0.0.84",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/homekit",
"version": "0.0.83",
"version": "0.0.84",
"dependencies": {
"hap-nodejs": "file:../HAP-NodeJS",
"lodash": "^4.17.21",

View File

@@ -40,5 +40,5 @@
"@types/qrcode": "^1.4.1",
"@types/url-parse": "^1.4.3"
},
"version": "0.0.83"
"version": "0.0.84"
}

View File

@@ -1,6 +1,6 @@
import sdk, { VideoCamera, Settings, Setting, ScryptedInterface, ObjectDetector, SettingValue, MediaStreamOptions } from "@scrypted/sdk";
import { SettingsMixinDeviceBase } from "../../../common/src/settings-mixin";
import { ContactSensor } from "../HAP-NodeJS/src/lib/definitions";
import { getH264DecoderArgs, getH264EncoderArgs } from "../../../common/src/ffmpeg-hardware-acceleration";
const { log, systemManager, deviceManager } = sdk;
@@ -84,12 +84,17 @@ export class CameraMixin extends SettingsMixinDeviceBase<any> implements Setting
}
if (showTranscodeArgs) {
const encoderArgs = getH264EncoderArgs();
const decoderArgs = getH264DecoderArgs();
settings.push({
title: 'Video Decoder Arguments',
key: "videoDecoderArguments",
value: this.storage.getItem('videoDecoderArguments'),
description: 'FFmpeg arguments used to decode input video.',
placeholder: '-hwaccel auto',
choices: Object.keys(decoderArgs),
combobox: true,
});
settings.push({
title: 'H264 Encoder Arguments',
@@ -97,6 +102,8 @@ export class CameraMixin extends SettingsMixinDeviceBase<any> implements Setting
value: this.storage.getItem('h264EncoderArguments'),
description: 'FFmpeg arguments used to encode h264 video.',
placeholder: '-vcodec h264_omx',
choices: Object.keys(encoderArgs),
combobox: true,
});
}
@@ -153,12 +160,24 @@ export class CameraMixin extends SettingsMixinDeviceBase<any> implements Setting
}
async putMixinSetting(key: string, value: SettingValue) {
if (key === 'videoDecoderArguments') {
const decoderArgs = getH264DecoderArgs();
value = decoderArgs[value.toString()]?.join(' ') || value;
}
if (key === 'h264EncoderArguments') {
const encoderArgs = getH264EncoderArgs();
const substitute = encoderArgs[value.toString()]?.join(' ');
value = substitute ? `\`${substitute}\`` : value;
}
if (key === 'objectDetectionContactSensors') {
this.storage.setItem(key, JSON.stringify(value));
}
else {
this.storage.setItem(key, value?.toString());
}
if (key === 'detectAudio' || key === 'linkedMotionSensor' || key === 'objectDetectionContactSensors') {
log.a(`You must reload the HomeKit plugin for the changes to ${this.name} to take effect.`);
}