You've already forked fm-dx-webserver
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:
@@ -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",
|
||||
|
||||
@@ -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
107
stream/parser.js
Normal 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 };
|
||||
Reference in New Issue
Block a user