fix(console): map Beep files to Audio/beep
Store and present Beep assets under Audio/beep while keeping legacy Audio/general reads working so existing files remain accessible during the directory transition.
This commit is contained in:
@@ -1585,6 +1585,8 @@
|
||||
source = `/media/audio/music/${encodeURIComponent(path.slice('Audio/music/'.length))}`;
|
||||
} else if (path.startsWith('Audio/voice/')) {
|
||||
source = `/media/audio/voice/${encodeURIComponent(path.slice('Audio/voice/'.length))}`;
|
||||
} else if (path.startsWith('Audio/beep/')) {
|
||||
source = `/media/audio/beep/${encodeURIComponent(path.slice('Audio/beep/'.length))}`;
|
||||
} else if (path.startsWith('Audio/general/')) {
|
||||
source = `/media/audio/general/${encodeURIComponent(path.slice('Audio/general/'.length))}`;
|
||||
} else if (path.startsWith('Audio/station/')) {
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
</div>
|
||||
|
||||
<div class="hint" id="hint_area">
|
||||
需要服务端已存在 lsts.wav(建议放在 /opt/CC-StationBroadcast/Audio/general/lsts.wav)。点击“合成”会自动中文 TTS 并拼接生成临时广播,随后可发布到所选站台。
|
||||
需要服务端已存在 lsts.wav(建议放在 /opt/CC-StationBroadcast/Audio/beep/lsts.wav)。点击“合成”会自动中文 TTS 并拼接生成临时广播,随后可发布到所选站台。
|
||||
</div>
|
||||
|
||||
<div id="preview_area" style="margin-top:12px; display:none;">
|
||||
|
||||
+57
-20
@@ -43,7 +43,8 @@ const uploadDir = path.join(__dirname, 'public', 'uploads');
|
||||
const audioRootDir = path.join(appRootDir, 'Audio');
|
||||
const audioMusicDir = path.join(audioRootDir, 'music');
|
||||
const audioVoiceDir = path.join(audioRootDir, 'voice');
|
||||
const audioGeneralDir = path.join(audioRootDir, 'general');
|
||||
const audioBeepDir = path.join(audioRootDir, 'beep');
|
||||
const audioGeneralLegacyDir = path.join(audioRootDir, 'general');
|
||||
const audioStationDir = path.join(audioRootDir, 'station');
|
||||
const listFilePath = path.join(appRootDir, 'list.txt');
|
||||
const tempBroadcastDir = path.join(appRootDir, 'temp-broadcast');
|
||||
@@ -54,10 +55,27 @@ if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });
|
||||
if (!fs.existsSync(audioRootDir)) fs.mkdirSync(audioRootDir, { recursive: true });
|
||||
if (!fs.existsSync(audioMusicDir)) fs.mkdirSync(audioMusicDir, { recursive: true });
|
||||
if (!fs.existsSync(audioVoiceDir)) fs.mkdirSync(audioVoiceDir, { recursive: true });
|
||||
if (!fs.existsSync(audioGeneralDir)) fs.mkdirSync(audioGeneralDir, { recursive: true });
|
||||
if (!fs.existsSync(audioBeepDir)) fs.mkdirSync(audioBeepDir, { recursive: true });
|
||||
if (!fs.existsSync(audioStationDir)) fs.mkdirSync(audioStationDir, { recursive: true });
|
||||
if (!fs.existsSync(tempBroadcastDir)) fs.mkdirSync(tempBroadcastDir, { recursive: true });
|
||||
|
||||
function getBeepAudioDirs() {
|
||||
const dirs = [audioBeepDir];
|
||||
if (audioGeneralLegacyDir !== audioBeepDir && fs.existsSync(audioGeneralLegacyDir)) {
|
||||
dirs.push(audioGeneralLegacyDir);
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
function sendBinaryFileFromCandidates(res, candidates) {
|
||||
for (const filePath of candidates) {
|
||||
if (fs.existsSync(filePath)) {
|
||||
return res.sendFile(filePath);
|
||||
}
|
||||
}
|
||||
return res.status(404).send('Not found');
|
||||
}
|
||||
|
||||
// Multer storage configuration
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
@@ -68,7 +86,7 @@ const storage = multer.diskStorage({
|
||||
} else if (file.fieldname === 'voiceAudioFiles') {
|
||||
cb(null, audioVoiceDir);
|
||||
} else if (file.fieldname === 'generalAudioFiles') {
|
||||
cb(null, audioGeneralDir);
|
||||
cb(null, audioBeepDir);
|
||||
} else if (file.fieldname === 'stationAudioFiles') {
|
||||
cb(null, audioStationDir);
|
||||
} else {
|
||||
@@ -114,7 +132,11 @@ function sendBinaryFile(res, filePath) {
|
||||
|
||||
app.get('/media/audio/general/:file', (req, res) => {
|
||||
const name = path.basename(String(req.params.file || ''));
|
||||
sendBinaryFile(res, path.join(audioGeneralDir, name));
|
||||
sendBinaryFileFromCandidates(res, getBeepAudioDirs().map(dir => path.join(dir, name)));
|
||||
});
|
||||
app.get('/media/audio/beep/:file', (req, res) => {
|
||||
const name = path.basename(String(req.params.file || ''));
|
||||
sendBinaryFileFromCandidates(res, getBeepAudioDirs().map(dir => path.join(dir, name)));
|
||||
});
|
||||
app.get('/media/audio/music/:file', (req, res) => {
|
||||
const name = path.basename(String(req.params.file || ''));
|
||||
@@ -142,6 +164,7 @@ app.get('/media', (req, res) => {
|
||||
routes: [
|
||||
'/media/audio/music/:file',
|
||||
'/media/audio/voice/:file',
|
||||
'/media/audio/beep/:file',
|
||||
'/media/audio/general/:file',
|
||||
'/media/audio/station/:file',
|
||||
'/media/temp/:file'
|
||||
@@ -585,7 +608,7 @@ function listMusicTracks() {
|
||||
const out = new Set();
|
||||
const scanDirs = [audioMusicDir];
|
||||
if (fs.existsSync(audioMusicDir) && fs.readdirSync(audioMusicDir).length === 0) {
|
||||
scanDirs.push(audioGeneralDir);
|
||||
scanDirs.push(...getBeepAudioDirs());
|
||||
}
|
||||
|
||||
for (const dir of scanDirs) {
|
||||
@@ -642,7 +665,7 @@ function getPlaybackAudioByBaseName(baseName) {
|
||||
for (const ext of STREAMABLE_AUDIO_EXTENSIONS) {
|
||||
const candidates = [
|
||||
path.join(audioMusicDir, `${base}${ext}`),
|
||||
path.join(audioGeneralDir, `${base}${ext}`),
|
||||
...getBeepAudioDirs().map(dir => path.join(dir, `${base}${ext}`)),
|
||||
path.join(audioStationDir, `${base}${ext}`)
|
||||
];
|
||||
for (const p of candidates) {
|
||||
@@ -657,7 +680,7 @@ function getPlaybackAudioByBaseName(baseName) {
|
||||
audioFormat: 'stream',
|
||||
streamUrl: getManagedMediaUrl(
|
||||
p.startsWith(audioStationDir) ? 'audio/station' :
|
||||
(p.startsWith(audioMusicDir) ? 'audio/music' : 'audio/general'),
|
||||
(p.startsWith(audioMusicDir) ? 'audio/music' : 'audio/beep'),
|
||||
path.basename(p)
|
||||
),
|
||||
durationSec
|
||||
@@ -667,7 +690,7 @@ function getPlaybackAudioByBaseName(baseName) {
|
||||
|
||||
for (const p of [
|
||||
path.join(audioMusicDir, `${base}.dfpwm`),
|
||||
path.join(audioGeneralDir, `${base}.dfpwm`),
|
||||
...getBeepAudioDirs().map(dir => path.join(dir, `${base}.dfpwm`)),
|
||||
path.join(audioStationDir, `${base}.dfpwm`)
|
||||
]) {
|
||||
if (!fs.existsSync(p)) continue;
|
||||
@@ -838,17 +861,27 @@ function resolveManagedPath(inputPath) {
|
||||
return { logicalPath: 'list.txt', fullPath: listFilePath };
|
||||
}
|
||||
|
||||
if (normalized === 'Audio/general/line.txt' || normalized === 'uploads/audio/general/line.txt') {
|
||||
return { logicalPath: 'Audio/general/line.txt', fullPath: path.join(audioGeneralDir, 'line.txt') };
|
||||
if (
|
||||
normalized === 'Audio/beep/line.txt' ||
|
||||
normalized === 'uploads/audio/beep/line.txt' ||
|
||||
normalized === 'Audio/general/line.txt' ||
|
||||
normalized === 'uploads/audio/general/line.txt'
|
||||
) {
|
||||
const fullPath = fs.existsSync(path.join(audioBeepDir, 'line.txt'))
|
||||
? path.join(audioBeepDir, 'line.txt')
|
||||
: path.join(audioGeneralLegacyDir, 'line.txt');
|
||||
return { logicalPath: 'Audio/beep/line.txt', fullPath };
|
||||
}
|
||||
|
||||
const prefixes = [
|
||||
{ prefix: 'Audio/music/', baseDir: audioMusicDir, logicalPrefix: 'Audio/music/' },
|
||||
{ prefix: 'Audio/voice/', baseDir: audioVoiceDir, logicalPrefix: 'Audio/voice/' },
|
||||
{ prefix: 'Audio/general/', baseDir: audioGeneralDir, logicalPrefix: 'Audio/general/' },
|
||||
{ prefix: 'Audio/beep/', baseDir: audioBeepDir, logicalPrefix: 'Audio/beep/' },
|
||||
{ prefix: 'Audio/general/', baseDir: audioGeneralLegacyDir, logicalPrefix: 'Audio/beep/' },
|
||||
{ prefix: 'uploads/audio/music/', baseDir: audioMusicDir, logicalPrefix: 'Audio/music/' },
|
||||
{ prefix: 'uploads/audio/voice/', baseDir: audioVoiceDir, logicalPrefix: 'Audio/voice/' },
|
||||
{ prefix: 'uploads/audio/general/', baseDir: audioGeneralDir, logicalPrefix: 'Audio/general/' },
|
||||
{ prefix: 'uploads/audio/beep/', baseDir: audioBeepDir, logicalPrefix: 'Audio/beep/' },
|
||||
{ prefix: 'uploads/audio/general/', baseDir: audioGeneralLegacyDir, logicalPrefix: 'Audio/beep/' },
|
||||
{ prefix: 'Audio/station/', baseDir: audioStationDir, logicalPrefix: 'Audio/station/' },
|
||||
{ prefix: 'uploads/audio/station/', baseDir: audioStationDir, logicalPrefix: 'Audio/station/' }
|
||||
];
|
||||
@@ -916,17 +949,21 @@ function getManagedFiles() {
|
||||
});
|
||||
}
|
||||
|
||||
if (fs.existsSync(audioGeneralDir)) {
|
||||
fs.readdirSync(audioGeneralDir).forEach(file => {
|
||||
const beepSeen = new Set();
|
||||
for (const dir of getBeepAudioDirs()) {
|
||||
if (!fs.existsSync(dir)) continue;
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
if (beepSeen.has(file)) return;
|
||||
beepSeen.add(file);
|
||||
if (file.endsWith('.dfpwm')) {
|
||||
const wavName = file.replace(/\.dfpwm$/, '.wav');
|
||||
if (fs.existsSync(path.join(audioGeneralDir, wavName))) return;
|
||||
if (beepSeen.has(wavName) || fs.existsSync(path.join(dir, wavName))) return;
|
||||
}
|
||||
const filePath = path.join(audioGeneralDir, file);
|
||||
const filePath = path.join(dir, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
files.push({
|
||||
name: file,
|
||||
path: `Audio/general/${file}`,
|
||||
path: `Audio/beep/${file}`,
|
||||
type: file === 'line.txt' ? 'config' : 'beep',
|
||||
size: stats.size,
|
||||
mtime: stats.mtimeMs
|
||||
@@ -1183,7 +1220,7 @@ function buildConcatListFile(seq) {
|
||||
|
||||
const candidates = [
|
||||
path.join(audioStationDir, `${item}.wav`),
|
||||
path.join(audioGeneralDir, `${item}.wav`)
|
||||
...getBeepAudioDirs().map(dir => path.join(dir, `${item}.wav`))
|
||||
];
|
||||
|
||||
const found = candidates.find(p => fs.existsSync(p));
|
||||
@@ -2527,7 +2564,7 @@ app.post('/api/tts/import', express.json(), (req, res) => {
|
||||
const jaSource = path.join(uploadDir, jaTemp);
|
||||
const safeStationCode = String(stationCode).replace(/\//g, '-');
|
||||
|
||||
const targetDir = type === 'line' ? audioGeneralDir : audioStationDir;
|
||||
const targetDir = type === 'line' ? audioBeepDir : audioStationDir;
|
||||
const zhDest = path.join(targetDir, `ch-${safeStationCode}.wav`);
|
||||
const jaDest = path.join(targetDir, `ja-${safeStationCode}.wav`);
|
||||
|
||||
@@ -2558,7 +2595,7 @@ function findWavByBaseName(baseName) {
|
||||
const safeBase = String(baseName || '').trim().replace(/\.wav$/i, '');
|
||||
if (!safeBase) return null;
|
||||
const candidates = [
|
||||
path.join(audioGeneralDir, `${safeBase}.wav`),
|
||||
...getBeepAudioDirs().map(dir => path.join(dir, `${safeBase}.wav`)),
|
||||
path.join(audioStationDir, `${safeBase}.wav`),
|
||||
path.join(uploadDir, `${safeBase}.wav`)
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user