Merge remote-tracking branch 'dev/1.2.x' into edge
This commit is contained in:
commit
9169ec65e3
@ -565,7 +565,7 @@ function api(db, channelDB, fillerDB, xmltvInterval, guideService ) {
|
||||
var data = `#EXTM3U url-tvg="${tvg}" x-tvg-url="${tvg}"\n`;
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
if (channels[i].stealth!==true) {
|
||||
data += `#EXTINF:0 tvg-id="${channels[i].number}" tvg-chno="${channels[i].number}" tvg-name="${channels[i].name}" tvg-logo="${channels[i].icon}" group-title="dizqueTV",${channels[i].name}\n`
|
||||
data += `#EXTINF:0 tvg-id="${channels[i].number}" CUID="${channels[i].number}" tvg-chno="${channels[i].number}" tvg-name="${channels[i].name}" tvg-logo="${channels[i].icon}" group-title="dizqueTV",${channels[i].name}\n`
|
||||
data += `${req.protocol}://${req.get('host')}/video?channel=${channels[i].number}\n`
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
const path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
const TARGET_VERSION = 700;
|
||||
const TARGET_VERSION = 701;
|
||||
|
||||
const STEPS = [
|
||||
// [v, v2, x] : if the current version is v, call x(db), and version becomes v2
|
||||
@ -33,6 +33,7 @@ const STEPS = [
|
||||
[ 501, 600, () => extractFillersFromChannels() ],
|
||||
[ 600, 601, (db) => addFPS(db) ],
|
||||
[ 601, 700, (db) => migrateWatermark(db) ],
|
||||
[ 700, 701, (db) => addScalingAlgorithm(db) ],
|
||||
]
|
||||
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
@ -395,6 +396,7 @@ function ffmpeg() {
|
||||
normalizeResolution: true,
|
||||
normalizeAudio: true,
|
||||
maxFPS: 60,
|
||||
scalingAlgorithm: "bicubic",
|
||||
}
|
||||
}
|
||||
|
||||
@ -746,6 +748,14 @@ function migrateWatermark(db, channelDB) {
|
||||
console.log("Done migrating watermarks in channels.");
|
||||
}
|
||||
|
||||
function addScalingAlgorithm(db) {
|
||||
let ffmpegSettings = db['ffmpeg-settings'].find()[0];
|
||||
let f = path.join(process.env.DATABASE, 'ffmpeg-settings.json');
|
||||
ffmpegSettings.scalingAlgorithm = "bicubic";
|
||||
fs.writeFileSync( f, JSON.stringify( [ffmpegSettings] ) );
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
initDB: initDB,
|
||||
defaultFFMPEG: ffmpeg,
|
||||
|
||||
@ -15,7 +15,12 @@ class FFMPEGInfo {
|
||||
}
|
||||
});
|
||||
});
|
||||
return s.match( /version ([^\s]+) Copyright/ )[1];
|
||||
var m = s.match( /version\s+([^\s]+)\s+.*Copyright/ )
|
||||
if (m == null) {
|
||||
console.error("ffmpeg -version command output not in the expected format: " + s);
|
||||
return s;
|
||||
}
|
||||
return m[1];
|
||||
} catch (err) {
|
||||
console.error("Error getting ffmpeg version", err);
|
||||
return "Error";
|
||||
|
||||
@ -9,6 +9,7 @@ class FFMPEG extends events.EventEmitter {
|
||||
super()
|
||||
this.opts = opts;
|
||||
this.errorPicturePath = `http://localhost:${process.env.PORT}/images/generic-error-screen.png`;
|
||||
this.ffmpegName = "unnamed ffmpeg";
|
||||
if (! this.opts.enableFFMPEGTranscoding) {
|
||||
//this ensures transcoding is completely disabled even if
|
||||
// some settings are true
|
||||
@ -255,7 +256,7 @@ class FFMPEG extends events.EventEmitter {
|
||||
|
||||
// Resolution fix: Add scale filter, current stream becomes [siz]
|
||||
let beforeSizeChange = currentVideo;
|
||||
let algo = "fast_bilinear";
|
||||
let algo = this.opts.scalingAlgorithm;
|
||||
let resizeMsg = "";
|
||||
if (
|
||||
(this.ensureResolution && ( streamStats.anamorphic || (iW != this.wantedW || iH != this.wantedH) ) )
|
||||
@ -321,10 +322,10 @@ class FFMPEG extends events.EventEmitter {
|
||||
var vert = Math.round( mpVert * iH / 100.0 );
|
||||
|
||||
let posAry = {
|
||||
'top-left': `${horz}:${vert}`,
|
||||
'top-right': `W-w-${horz}:${vert}`,
|
||||
'bottom-left': `${horz}:H-h-${vert}`,
|
||||
'bottom-right': `W-w-${horz}:H-h-${vert}`,
|
||||
'top-left': `x=${horz}:y=${vert}`,
|
||||
'top-right': `x=W-w-${horz}:y=${vert}`,
|
||||
'bottom-left': `x=${horz}:y=H-h-${vert}`,
|
||||
'bottom-right': `x=W-w-${horz}:y=H-h-${vert}`,
|
||||
}
|
||||
let icnDur = ''
|
||||
if (watermark.duration > 0) {
|
||||
@ -339,7 +340,11 @@ class FFMPEG extends events.EventEmitter {
|
||||
if (typeof(p) === 'undefined') {
|
||||
throw Error("Invalid watermark position: " + watermark.position);
|
||||
}
|
||||
videoComplex += `;${currentVideo}${waterVideo}overlay=${p}${icnDur}[comb]`
|
||||
let overlayShortest = "";
|
||||
if (watermark.animated) {
|
||||
overlayShortest = "shortest=1:";
|
||||
}
|
||||
videoComplex += `;${currentVideo}${waterVideo}overlay=${overlayShortest}${p}${icnDur}[comb]`
|
||||
currentVideo = '[comb]';
|
||||
}
|
||||
|
||||
@ -464,30 +469,45 @@ class FFMPEG extends events.EventEmitter {
|
||||
ffmpegArgs.push(`pipe:1`)
|
||||
|
||||
let doLogs = this.opts.logFfmpeg && !isConcatPlaylist;
|
||||
if (this.hasBeenKilled) {
|
||||
return ;
|
||||
}
|
||||
this.ffmpeg = spawn(this.ffmpegPath, ffmpegArgs, { stdio: ['ignore', 'pipe', (doLogs?process.stderr:"ignore") ] } );
|
||||
if (this.hasBeenKilled) {
|
||||
this.ffmpeg.kill("SIGKILL");
|
||||
return;
|
||||
}
|
||||
|
||||
let ffmpegName = (isConcatPlaylist ? "Concat FFMPEG": "Stream FFMPEG");
|
||||
|
||||
this.ffmpegName = (isConcatPlaylist ? "Concat FFMPEG": "Stream FFMPEG");
|
||||
|
||||
this.ffmpeg.on('error', (code, signal) => {
|
||||
console.log( `${this.ffmpegName} received error event: ${code}, ${signal}` );
|
||||
});
|
||||
this.ffmpeg.on('exit', (code, signal) => {
|
||||
if (code === null) {
|
||||
console.log( `${ffmpegName} exited due to signal: ${signal}` );
|
||||
if (!this.hasBeenKilled) {
|
||||
console.log( `${this.ffmpegName} exited due to signal: ${signal}` );
|
||||
} else {
|
||||
console.log( `${this.ffmpegName} exited due to signal: ${signal} as expected.`);
|
||||
}
|
||||
this.emit('close', code)
|
||||
} else if (code === 0) {
|
||||
console.log( `${ffmpegName} exited normally.` );
|
||||
console.log( `${this.ffmpegName} exited normally.` );
|
||||
this.emit('end')
|
||||
} else if (code === 255) {
|
||||
if (this.hasBeenKilled) {
|
||||
console.log( `${ffmpegName} finished with code 255.` );
|
||||
console.log( `${this.ffmpegName} finished with code 255.` );
|
||||
this.emit('close', code)
|
||||
return;
|
||||
}
|
||||
if (! this.sentData) {
|
||||
this.emit('error', { code: code, cmd: `${this.opts.ffmpegPath} ${ffmpegArgs.join(' ')}` })
|
||||
}
|
||||
console.log( `${ffmpegName} exited with code 255.` );
|
||||
console.log( `${this.ffmpegName} exited with code 255.` );
|
||||
this.emit('close', code)
|
||||
} else {
|
||||
console.log( `${ffmpegName} exited with code ${code}.` );
|
||||
console.log( `${this.ffmpegName} exited with code ${code}.` );
|
||||
this.emit('error', { code: code, cmd: `${this.opts.ffmpegPath} ${ffmpegArgs.join(' ')}` })
|
||||
}
|
||||
});
|
||||
@ -495,9 +515,11 @@ class FFMPEG extends events.EventEmitter {
|
||||
return this.ffmpeg.stdout;
|
||||
}
|
||||
kill() {
|
||||
if (typeof this.ffmpeg != "undefined") {
|
||||
this.hasBeenKilled = true;
|
||||
this.ffmpeg.kill()
|
||||
console.log(`${this.ffmpegName} RECEIVED kill() command`);
|
||||
this.hasBeenKilled = true;
|
||||
if (typeof(this.ffmpeg) != "undefined") {
|
||||
console.log(`${this.ffmpegName} this.ffmpeg.kill()`);
|
||||
this.ffmpeg.kill("SIGKILL")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +60,13 @@ module.exports = function (dizquetv, resolutionOptions) {
|
||||
{id: 60, description: "60 frames per second"},
|
||||
{id: 120, description: "120 frames per second"},
|
||||
];
|
||||
scope.scalingOptions = [
|
||||
{id: "bicubic", description: "bicubic (default)"},
|
||||
{id: "fast_bilinear", description: "fast_bilinear"},
|
||||
{id: "lanczos", description: "lanczos"},
|
||||
{id: "spline", description: "spline"},
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -740,7 +740,7 @@
|
||||
<label class="form-check-label" for="overlayAnimated">
|
||||
Animated Image
|
||||
</label>
|
||||
<small class='text-muted form-text' >Tick this if and only if the watermark is an animated GIF or PNG. It will make it loop or not loop according to the image's configuration. If the image is not animated, an error will be generated.</small>
|
||||
<small class='text-muted form-text' >Tick this if and only if the watermark is an animated GIF or PNG. It will make it loop or not loop according to the image's configuration. If the image is not animated, there will be playback errors.</small>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
@ -91,10 +91,18 @@
|
||||
<br />
|
||||
<label>Video Buffer Size (k)</label>
|
||||
<input type="number" class="form-control form-control-sm" ng-model="settings.videoBufSize"/>
|
||||
<br />
|
||||
<label>Max Frame Rate</label>
|
||||
<select class='form-control custom-select' ng-model="settings.maxFPS" ria-describedby="fpsHelp"
|
||||
ng-options="o.id as o.description for o in fpsOptions" ></select>
|
||||
<small id='fpsHelp' class='form-text text-muted'>Will transcode videos that have FPS higher than this.</small>
|
||||
|
||||
<br />
|
||||
<label>Scaling Algorithm</label>
|
||||
<select class='form-control custom-select' ng-model="settings.scalingAlgorithm" ria-describedby="scalingHelp"
|
||||
ng-options="o.id as o.description for o in scalingOptions" ></select>
|
||||
<small id='scalingHelp' class='form-text text-muted'>Scaling algorithm to use when the transcoder needs to change the video size.</small>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user