mirror of
https://github.com/koush/scrypted.git
synced 2026-07-09 08:30:39 +01:00
homekit: ffmpeg encoder suggestions
This commit is contained in:
124
common/src/ffmpeg-hardware-acceleration.ts
Normal file
124
common/src/ffmpeg-hardware-acceleration.ts
Normal 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;
|
||||
}
|
||||
4
plugins/homekit/package-lock.json
generated
4
plugins/homekit/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
"@types/qrcode": "^1.4.1",
|
||||
"@types/url-parse": "^1.4.3"
|
||||
},
|
||||
"version": "0.0.83"
|
||||
"version": "0.0.84"
|
||||
}
|
||||
|
||||
@@ -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.`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user