feat: setup proper channel api
This commit is contained in:
66
controllers/ChannelController.js
Normal file
66
controllers/ChannelController.js
Normal file
@@ -0,0 +1,66 @@
|
||||
const ffmpegService = require('../services/FFmpegService');
|
||||
const storageService = require('../services/StorageService');
|
||||
const Channel = require('../models/Channel');
|
||||
|
||||
let channels = [new Channel('DEFAULT_CHANNEL', process.env.DEFAULT_CHANNEL_URL)];
|
||||
let currentChannel = channels[0];
|
||||
|
||||
function setCurrent(req, res) {
|
||||
const { channelName } = req.body || {};
|
||||
|
||||
if (!channelName) {
|
||||
return res.status(400).json({ status: 'error', message: 'channelName is required' });
|
||||
}
|
||||
|
||||
const nextChannel = channels.find(channel => channel.name === channelName);
|
||||
if (!nextChannel) {
|
||||
res.status(400).json({ status: 'error', message: 'Channel does not exist' });
|
||||
}
|
||||
|
||||
if (currentChannel !== nextChannel) {
|
||||
const segmentNumber = storageService.getNextSegmentNumber();
|
||||
storageService.clearStorage();
|
||||
currentChannel = nextChannel;
|
||||
ffmpegService.startFFmpeg(nextChannel.url, segmentNumber);
|
||||
}
|
||||
res.status(200).json({ status: 'success', channelUrl: currentChannel.url });
|
||||
}
|
||||
|
||||
|
||||
function getCurrent(_, res) {
|
||||
if (currentChannel) {
|
||||
res.status(200).json({ channelName: currentChannel.name, channelUrl: currentChannel.url });
|
||||
} else {
|
||||
res.status(404).json({ status: 'error', message: 'No channel active' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getChannels(_, res) {
|
||||
res.status(200).json({ channels });
|
||||
}
|
||||
|
||||
function addChannel(req, res) {
|
||||
const { name, url } = req.body;
|
||||
|
||||
if (!name || !url) {
|
||||
return res.status(400).json({ status: 'error', message: 'Channel name and URL are required' });
|
||||
}
|
||||
|
||||
const channelExists = channels.some(channel => channel.url === url);
|
||||
if (channelExists) {
|
||||
return res.status(409).json({ status: 'error', message: 'Channel already exists' });
|
||||
}
|
||||
|
||||
const newChannel = new Channel(name, url);
|
||||
channels.push(newChannel);
|
||||
res.status(201).json({ status: 'success', message: 'Channel added', channel: newChannel });
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
setCurrent,
|
||||
getCurrent,
|
||||
getChannels,
|
||||
addChannel
|
||||
};
|
||||
@@ -1,41 +1,22 @@
|
||||
const ffmpegService = require('../services/FFmpegService');
|
||||
const storageService = require('../services/StorageService');
|
||||
|
||||
let currentChannelId = process.env.DEFAULT_CHANNEL_ID;
|
||||
|
||||
function setChannel(req, res) {
|
||||
const { id: channelId } = req.params;
|
||||
if (channelId && currentChannelId != channelId) {
|
||||
function start() {
|
||||
if (!ffmpegService.isFFmpegRunning()) {
|
||||
const segmentNumber = storageService.getNextSegmentNumber();
|
||||
storageService.clearStorage();
|
||||
currentChannelId = channelId;
|
||||
ffmpegService.startFFmpeg(channelId, segmentNumber);
|
||||
res.status(200).json({ status: 'success', channelId: currentChannelId });
|
||||
} else {
|
||||
res.status(400).json({ status: 'error', message: 'No channel set' });
|
||||
ffmpegService.startFFmpeg(process.env.DEFAULT_CHANNEL_URL, segmentNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getChannel(_, res) {
|
||||
if (currentChannelId) {
|
||||
res.status(200).json({ channelId: currentChannelId });
|
||||
} else {
|
||||
res.status(404).json({ status: 'error', message: 'No channel set' });
|
||||
}
|
||||
}
|
||||
|
||||
function stop(req, res) {
|
||||
function stop() {
|
||||
if (ffmpegService.isFFmpegRunning()) {
|
||||
ffmpegService.stopFFmpeg();
|
||||
res.status(200).json({ status: 'success', message: 'ffmpeg-Process terminated' });
|
||||
} else {
|
||||
res.status(400).json({ status: 'error', message: 'No ffmpeg-process running' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setChannel,
|
||||
getChannel,
|
||||
start,
|
||||
stop
|
||||
};
|
||||
|
||||
16
index.js
16
index.js
@@ -1,21 +1,27 @@
|
||||
const express = require('express');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
const channelController = require('./controllers/ChannelController');
|
||||
const streamController = require('./controllers/StreamController');
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
|
||||
const apiRouter = express.Router();
|
||||
|
||||
apiRouter.post('/current', channelController.setCurrent);
|
||||
apiRouter.get('/current', channelController.getCurrent);
|
||||
|
||||
apiRouter.post('/set-channel/:id', streamController.setChannel);
|
||||
apiRouter.get('/get-channel', streamController.getChannel);
|
||||
apiRouter.post('/stop', streamController.stop);
|
||||
apiRouter.get('/', channelController.getChannels);
|
||||
apiRouter.post('/add', channelController.addChannel);
|
||||
|
||||
app.use('/api', apiRouter);
|
||||
app.use('/channels', apiRouter);
|
||||
|
||||
const PORT = 5000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server listening on Port ${PORT}`);
|
||||
streamController.setChannel({ params: { id: process.env.DEFAULT_CHANNEL_ID } }, { status: () => ({ json: () => {} }) });
|
||||
streamController.start();
|
||||
});
|
||||
|
||||
8
models/Channel.js
Normal file
8
models/Channel.js
Normal file
@@ -0,0 +1,8 @@
|
||||
class Channel {
|
||||
constructor(name, url) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Channel;
|
||||
@@ -2,26 +2,25 @@ const { spawn } = require('child_process');
|
||||
require('dotenv').config();
|
||||
|
||||
let currentFFmpegProcess = null;
|
||||
const BASE_URL = process.env.BASE_URL;
|
||||
const STORAGE_PATH = process.env.STORAGE_PATH;
|
||||
|
||||
function startFFmpeg(channelId, startNumber) {
|
||||
function startFFmpeg(channelUrl, startNumber) {
|
||||
if (currentFFmpegProcess) {
|
||||
console.log('Terminate previous ffmpeg-Prozess...');
|
||||
currentFFmpegProcess.kill('SIGTERM');
|
||||
}
|
||||
|
||||
const streamUrl = `${BASE_URL}${channelId}`;
|
||||
console.log(`Start ffmpeg with URL: ${streamUrl}`);
|
||||
console.log(`Start ffmpeg with URL: ${channelUrl}`);
|
||||
|
||||
currentFFmpegProcess = spawn('ffmpeg', [
|
||||
'-i', streamUrl,
|
||||
'-i', channelUrl,
|
||||
'-c', 'copy',
|
||||
'-f', 'hls',
|
||||
'-hls_time', '8',
|
||||
'-hls_list_size', '5',
|
||||
'-hls_flags', 'delete_segments',
|
||||
'-hls_flags', 'delete_segments+program_date_time',
|
||||
'-start_number', startNumber,
|
||||
'/mnt/streams/recordings/playlist.m3u8'
|
||||
`${STORAGE_PATH}/playlist.m3u8`
|
||||
]);
|
||||
|
||||
currentFFmpegProcess.stdout.on('data', (data) => {
|
||||
|
||||
Reference in New Issue
Block a user