1
0
mirror of https://github.com/KubaPro010/fm-dx-webserver.git synced 2026-02-26 22:13:53 +01:00

ejs + webadmin + bugfixes

This commit is contained in:
NoobishSVK
2024-02-04 16:56:35 +01:00
parent d6b128c0bd
commit c848bef002
27 changed files with 1329 additions and 161 deletions

View File

@@ -1,4 +1,17 @@
"use strict";
var fs = require('fs');
let serverConfig = {
audio: {
audioBitrate: "128k"
},
};
if(fs.existsSync('./config.json')) {
const configFileContents = fs.readFileSync('./config.json', 'utf8');
serverConfig = JSON.parse(configFileContents);
}
/*
Stdin streamer is part of 3LAS (Low Latency Live Audio Streaming)
https://github.com/JoJoBond/3LAS
@@ -340,7 +353,7 @@ class FallbackProviderMp3 extends AFallbackProvider {
"-ac", this.Server.Channels.toString(),
"-i", "pipe:0",
"-c:a", "libmp3lame",
"-b:a", Settings.FallbackMp3Bitrate.toString() + "k",
"-b:a", serverConfig.audio.audioBitrate,
"-ac", this.Server.Channels.toString(),
"-reservoir", "0",
"-f", "mp3", "-write_xing", "0", "-id3v2_version", "0",

View File

@@ -1,27 +1,44 @@
const { spawn } = require('child_process');
const config = require('../userconfig.js');
const fs = require('fs');
const consoleCmd = require('../console.js');
let serverConfig = {
webserver: {
audioPort: "8081"
},
audio: {
audioDevice: "Microphone (High Definition Audio Device)",
audioChannels: 2,
audioBitrate: "128k"
},
};
if(fs.existsSync('./config.json')) {
const configFileContents = fs.readFileSync('./config.json', 'utf8');
serverConfig = JSON.parse(configFileContents);
}
function enableAudioStream() {
var ffmpegCommand;
// Specify the command and its arguments
const command = 'ffmpeg';
const flags = '-fflags +nobuffer+flush_packets -flags low_delay -rtbufsize 6192 -probesize 64';
const codec = '-acodec pcm_s16le -ar 48000 -ac 2';
const output = '-f s16le -fflags +nobuffer+flush_packets -packetsize 384 -flush_packets 1 -bufsize 960';
const flags = `-fflags +nobuffer+flush_packets -flags low_delay -rtbufsize 6192 -probesize 32`;
const codec = `-acodec pcm_s16le -ar 32000 -ac ${serverConfig.audio.audioChannels}`;
const output = `-f s16le -fflags +nobuffer+flush_packets -packetsize 384 -flush_packets 1 -bufsize 960`;
// Combine all the settings for the ffmpeg command
if (process.platform === 'win32') {
// Windows
ffmpegCommand = `${flags} -f dshow -i audio="${config.audioDeviceName}" ${codec} ${output} pipe:1 | node stream/3las.server.js -port ${config.audioPort} -samplerate 48000 -channels 2`;
ffmpegCommand = `${flags} -f dshow -i audio="${serverConfig.audio.audioDevice}" ${codec} ${output} pipe:1 | node stream/3las.server.js -port ${serverConfig.webserver.audioPort} -samplerate 32000 -channels ${serverConfig.audio.audioChannels}`;
} else {
// Linux
ffmpegCommand = `${flags} -f alsa -i "${config.audioDeviceName}" ${codec} ${output} pipe:1 | node stream/3las.server.js -port ${config.audioPort} -samplerate 48000 -channels 2`;
ffmpegCommand = `${flags} -f alsa -i "${serverConfig.audio.audioDevice}" ${codec} ${output} pipe:1 | node stream/3las.server.js -port ${serverConfig.webserver.audioPort} -samplerate 32000 -channels ${serverConfig.audio.audioChannels}`;
}
consoleCmd.logInfo("Launching audio stream on port " + config.audioPort + ".");
consoleCmd.logInfo("Using audio device: " + serverConfig.audio.audioDevice);
consoleCmd.logInfo("Launching audio stream on port " + serverConfig.webserver.audioPort + ".");
// Spawn the child process
if(config.audioDeviceName.length > 2) {
if(serverConfig.audio.audioDevice.length > 2) {
const childProcess = spawn(command, [ffmpegCommand], { shell: true });
// Handle the output of the child process (optional)

107
stream/parser.js Normal file
View File

@@ -0,0 +1,107 @@
'use strict';
const exec = require('child_process').exec;
const platform = process.platform;
function parseAudioDevice(options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
options = options || {};
const ffmpegPath = options.ffmpegPath || 'ffmpeg';
const callbackExists = typeof callback === 'function';
let inputDevice, prefix, audioSeparator, alternativeName, deviceParams;
switch (platform) {
case 'win32':
inputDevice = 'dshow';
prefix = /\[dshow/;
audioSeparator = /DirectShow\saudio\sdevices/;
alternativeName = /Alternative\sname\s*?\"(.*?)\"/;
deviceParams = /\"(.*?)\"/;
break;
case 'darwin':
inputDevice = 'avfoundation';
prefix = /^\[AVFoundation/;
audioSeparator = /AVFoundation\saudio\sdevices/;
deviceParams = /^\[AVFoundation.*?\]\s\[(\d*?)\]\s(.*)$/;
break;
case 'linux':
exec("cat /proc/asound/cards | sed -r 's/^ *([0-9]+) \\[(.*) *\\]: (.*)/hw:\\2/' | grep -E '^hw:'", (err, stdout) => {
audioDevices = stdout.trim().split('\n').map(device => ({ name: device }));
const result = { audioDevices };
if (callbackExists) {
callback(result);
} else {
Promise.resolve(result);
}
});
break;
}
const searchPrefix = (line) => (line.search(prefix) > -1);
const searchAudioSeparator = (line) => isVideo && (line.search(audioSeparator) > -1);
const searchAlternativeName = (line) => (platform === 'win32') && (line.search(/Alternative\sname/) > -1);
let videoDevices = [];
let audioDevices = [];
let isVideo = true;
const execute = (fulfill, reject) => {
exec(`${ffmpegPath} -f ${inputDevice} -list_devices true -i ""`, (err, stdout, stderr) => {
stderr.split("\n")
.filter(searchPrefix)
.forEach((line) => {
const deviceList = isVideo ? videoDevices : audioDevices;
if (searchAudioSeparator(line)) {
isVideo = false;
return;
}
if (searchAlternativeName(line)) {
const lastDevice = deviceList[deviceList.length - 1];
lastDevice.alternativeName = line.match(alternativeName)[1];
return;
}
const params = line.match(deviceParams);
if (params) {
let device;
switch (platform) {
case 'win32':
device = {
name: params[1]
};
break;
case 'darwin':
device = {
id: parseInt(params[1]),
name: params[2]
};
break;
case 'linux':
device = {
name: params[1]
};
break;
}
deviceList.push(device);
}
});
const result = { videoDevices, audioDevices };
if (callbackExists) {
callback(result);
} else {
fulfill(result);
}
});
};
if (callbackExists) {
execute();
} else {
return new Promise(execute);
}
}
module.exports = { parseAudioDevice };