diff --git a/imports/ui/App.jsx b/imports/ui/App.jsx index 4797a52d..b5fe5930 100644 --- a/imports/ui/App.jsx +++ b/imports/ui/App.jsx @@ -22,7 +22,6 @@ import TabPlugins from './plugins/tab_Plugins.jsx'; import TabSearch from './tab_Search.jsx'; import TabTranscoding from './transcoding/tab_Transcoding.jsx'; import TabBackups from './tab_Backups.jsx'; -import TabHire from './tab_Hire.jsx'; const tabs = [ {path: '/tdarr/', text: 'Tdarr', component: TabTranscoding}, @@ -34,7 +33,6 @@ const tabs = [ {path: '/logs/', text: 'Logs', component: TabLog}, {path: '/help/', text: 'Help', component: TabHelp}, {path: '/backups/', text: 'Backups', component: TabBackups}, - {path: '/hire/', text: 'Hire', component: TabHire}, {path: '/', text: 'Dev', component: TabDev}, ]; @@ -47,7 +45,7 @@ export default AppRouter = () => { const [currentVersion, setVersion] = React.useState(''); - const [newVersion, setNewVersion] = React.useState(1.107); + const [newVersion, setNewVersion] = React.useState(1.108); diff --git a/imports/ui/libraries/tab_Libraries.jsx b/imports/ui/libraries/tab_Libraries.jsx index 90a2e910..57f3a8d3 100644 --- a/imports/ui/libraries/tab_Libraries.jsx +++ b/imports/ui/libraries/tab_Libraries.jsx @@ -86,12 +86,28 @@ class App extends Component { expanded:true, navItemSelected:"navSourceFolder", pluginID:'', - pluginIDs:[{ + pluginIDs:[ + { _id:"Tdarr_Plugin_lmg1_Reorder_Streams", checked:true, source:"Community", priority:0, - }], + }, + { + _id:"Tdarr_Plugin_MC93_Migz1FFMPEG_CPU", + checked:true, + source:"Community", + priority:1, + }, + { + _id:"Tdarr_Plugin_MC93_Migz1FFMPEG", + checked:false, + source:"Community", + priority:2, + }, + + + ], pluginValid:false, pluginCommunity:true, handbrake:true, diff --git a/imports/ui/styles/main.scss b/imports/ui/styles/main.scss index 65b0ae2f..b61ad7b2 100644 --- a/imports/ui/styles/main.scss +++ b/imports/ui/styles/main.scss @@ -440,42 +440,63 @@ input[type="text"] justify-content: center; } + +.workerContainer{ + display: 'inline-block'; + border-radius: 5px; + width:400px; + margin:1em; +} + + +.workerContainerItems{ + padding:1em 2em; + +} + .workerItemsGrid{ display: grid; grid-template-columns: repeat(4, 1fr); - margin:1em; + text-align: left; + } -.workerContainer{ - display: 'inline-block'; +.workerDetailsGrid{ + display: grid; + grid-template-columns: repeat(2, 1fr); + text-align: left; - border-radius: 5px; - width:400px; } +.workerGrid-item { + + margin: 0 1em; + padding: 0 0 0 0; +} + +table.workerDetailTable td { + color: black; +} + +.workerBreakLine{ + word-break: break-all; +} + + .borderStyleGeneral{ border: 2px solid black; border-radius: 5px; background-color:#373737; - margin:1em; - padding:1em; - } .borderStyleTranscode{ border: 2px solid #66ccff; border-radius: 5px; background-color:#373737; - margin:1em; - padding:1em; - } .borderStyleHealthCheck{ border: 2px solid #4CAF50; border-radius: 5px; - background-color:#373737; - margin:1em; - padding:1em; - + background-color:#373737; } @@ -1304,14 +1325,7 @@ table.scheduleTable tr:hover { } } -table.workerDetailTable td { - - color: black; - vertical-align: text-top; - - -} .introText{ diff --git a/imports/ui/tab_Dev.jsx b/imports/ui/tab_Dev.jsx index f70cac1c..3294e6eb 100644 --- a/imports/ui/tab_Dev.jsx +++ b/imports/ui/tab_Dev.jsx @@ -123,6 +123,26 @@ export default class App extends Component { +

Beta v1.107 release [4th April 2020]: + +
Changes: + +
-[New] tdarr_aio ffmpeg updated to 4.2.2 with libaom enabled +
-[New] Small UI changes and help info updates +
-[New] Folder watch: Option to use file system events (FSE) instead of polling (try if polling causes high CPU/disk IO). FSE may not work with all drives/shares. +
-[New] HandBrake and FFmpeg binary paths passed to plugins +
-[Improvement] Error shown if problem with reading plugin +
-[Improvement] New files appended with '.partial' while copying to source to prevent app/services scanning temp file +
-[Improvement] Logs saved to txt file (inside Tdarr/Logs) instead of DB +
-[Fix] Detect if files are replaced with file of same file name+extension +
-[Fix] Limit transcode error logs to 200 lines (Sometimes 70,000+ lines which causes DB issues) +
-[Fix] Info log added for post-processing plugins +
-[Fix] Prevent corrupt item causing whole backup restore process to stop +
+
+ +

+

Beta v1.106 release [20th March 2020]:
Changes: diff --git a/imports/ui/tab_Dev_latest.jsx b/imports/ui/tab_Dev_latest.jsx index 24f63544..1b24c266 100644 --- a/imports/ui/tab_Dev_latest.jsx +++ b/imports/ui/tab_Dev_latest.jsx @@ -29,21 +29,15 @@ export default class App extends Component {

-

Beta v1.107 release [4th April 2020]: +

Beta v1.108 release [18th April 2020]:
Changes: -
-[New] tdarr_aio ffmpeg updated to 4.2.2 with libaom enabled -
-[New] Small UI changes and help info updates -
-[New] Folder watch: Option to use file system events (FSE) instead of polling (try if polling causes high CPU/disk IO). FSE may not work with all drives/shares. -
-[New] HandBrake and FFmpeg binary paths passed to plugins -
-[Improvement] Error shown if problem with reading plugin -
-[Improvement] New files appended with '.partial' while copying to source to prevent app/services scanning temp file -
-[Improvement] Logs saved to txt file (inside Tdarr/Logs) instead of DB -
-[Fix] Detect if files are replaced with file of same file name+extension -
-[Fix] Limit transcode error logs to 200 lines (Sometimes 70,000+ lines which causes DB issues) -
-[Fix] Info log added for post-processing plugins -
-[Fix] Prevent corrupt item causing whole backup restore process to stop +
-[New] Add default plugins to new libraries +
-[Improvement] Check other properties to calculate bitrate +
-[Improvement] Reduce worker spawn rate +
-[Improvement] Change process priority from "Below normal" to "Low" when switch enabled (Win) +
-[Fix] Prevent folder watcher re-adding already scanned files

diff --git a/imports/ui/tab_Hire.jsx b/imports/ui/tab_Hire.jsx deleted file mode 100644 index 0134feb7..00000000 --- a/imports/ui/tab_Hire.jsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { Component } from 'react'; -import { Meteor } from 'meteor/meteor'; -import { Button } from 'react-bootstrap'; - - - - - - -export default class App extends Component { - - constructor(props) { - super(props); - - } - - componentDidMount() { - - } - - - render() { - - - - return ( - - - -

-
- - - -

Hi!

-
- -
-
- -

I'm looking to do some freelance work with regards to the following:

-
- -

Custom versions, special/urgent requests or 1-to-1 help for my apps (below)

-

Small/medium sized cross platform desktop applications

-

Small/medium sized websites/web apps

-

Tools, utilities or scripts

-

Transcode related projects

-

Remote junior/graduate role (or on-site in UK)

-

Learning to code

- - -
-

$20/hr through Paypal. If you have any questions or know anyone looking for the above then please don't hesitate to contact me!

-
- -

Contact: roystubbs.dev@gmail.com

-

Website: roystubbs.dev

- - -
-

Thanks, Roy

- -
-
- -

My Apps:

-
- HBBatchBeast -

A free GUI application for HandBrake and FFmpeg/FFprobe on Windows, macOS and Linux (+ Linux Docker image) with - an emphasis on multi HandBrake/FFmpeg instance batch conversion (including recursive folder scans and folder watching). - The destination folder structure is kept the same as the source folder structure. Media in subfolders is also converted. - Multiple folders can be monitored and different conversion presets can be specified for each folder.

- -
- - Tdarr -

Tdarr is a self hosted web-app for automating media library transcode/remux management and making sure your files - are exactly how you need them to be in terms of codecs/streams/containers etc. Designed to work alongside Sonarr/Radarr - and built with the aim of modularisation, parallelisation and scalability, each library you add has its own transcode - settings, filters and schedule. Workers can be fired up and closed down as necessary, and are split into 3 types - 'general', - 'transcode' and 'health check'. Worker limits can be managed by the scheduler as well as manually.

- -
-
- -
-
- - ); - } -} diff --git a/imports/ui/transcoding/tab_Transcoding_Worker.jsx b/imports/ui/transcoding/tab_Transcoding_Worker.jsx index 6a0eff0a..173b7b4b 100644 --- a/imports/ui/transcoding/tab_Transcoding_Worker.jsx +++ b/imports/ui/transcoding/tab_Transcoding_Worker.jsx @@ -23,7 +23,7 @@ export default class Worker extends Component { constructor(props) { super(props); - this.state = { infoHidden: true,oldProgress:"Calculating..." } + this.state = { infoHidden: true, oldProgress: "Calculating..." } } componentDidMount() { @@ -57,11 +57,11 @@ export default class Worker extends Component { return this.fancyTimeFormat(secsSinceStart) } - transcodeReason(info){ + transcodeReason(info) { info = info.split("\n") - info = info.map( row =>{row}
) + info = info.map(row => {row}
) return info @@ -86,8 +86,9 @@ export default class Worker extends Component { + return ( -
+
@@ -99,11 +100,11 @@ export default class Worker extends Component {
-
-
+
+
{ @@ -117,8 +118,8 @@ export default class Worker extends Component {
-
-
+
+

{this.props.worker.mode == 'transcode' ? "Transcode" : this.props.worker.mode == 'healthcheck' ? "Heath check" : "General(" + workerModes[this.props.worker.modeType] + ")"}

@@ -126,16 +127,16 @@ export default class Worker extends Component {
-
+
-

ETA{'\u00A0'}{'\u00A0'}{ this.props.worker.modeType == 'healthcheck' && this.props.worker.CLIType == "FFmpeg" ? "None" :this.props.worker.percentage <= 100 ? this.props.worker.ETA : ''}

+

ETA{'\u00A0'}{'\u00A0'}{this.props.worker.modeType == 'healthcheck' && this.props.worker.CLIType == "FFmpeg" ? "None" : this.props.worker.percentage <= 100 ? this.props.worker.ETA : ''}

- -
-

{this.props.worker.lastPluginDetails.number ? this.props.worker.lastPluginDetails.number : ''}

+
+ +

{this.props.worker.lastPluginDetails.number ? this.props.worker.lastPluginDetails.number : ''}

@@ -151,113 +152,121 @@ export default class Worker extends Component {
-
- {this.props.worker.percentage + '%'}

, - trailColor: '#373737', - color: '#04dac5' - }, +
+ {this.props.worker.percentage + '%'}

, + trailColor: '#373737', + color: '#04dac5' + }, + } } - } - /> -
+ /> +
100 ? '' : 'd-none'}>
- {'-'}

, - trailColor: '#373737', - color: '#04dac5' - }, + {'-'}

, + trailColor: '#373737', + color: '#04dac5' + }, + } } - } - />
+ />
-

Frame: {this.props.worker.percentage / 100}

+

Frame: {this.props.worker.percentage / 100}

-
- +
+ -
+
- - - - - +

Path:

{this.props.worker.file}

CLI:

{this.props.worker.CLIType}

+ - + + + - - + - + +

Preset:

{this.props.worker.preset}

Path:

{this.props.worker.file}

CLI:

{this.props.worker.CLIType}

Preset:

{this.props.worker.preset}

Process reasons:

{this.transcodeReason(this.props.worker.cliLogAdd)}

Start time:

{this.toTime(this.props.worker.startTime)}

Process reasons:

{this.transcodeReason(this.props.worker.cliLogAdd)}

Duration:

{this.duration(this.props.worker.startTime)}

-

Original size

{this.props.worker.sourcefileSizeInGbytes == undefined ? 0 : (this.props.worker.sourcefileSizeInGbytes < 1 ? parseFloat((this.props.worker.sourcefileSizeInGbytes * 1000).toPrecision(4)) +" MB" : parseFloat((this.props.worker.sourcefileSizeInGbytes).toPrecision(4)) + " GB")}

-

Output file size

{this.props.worker.outputFileSizeInGbytes == undefined ? 0 : (this.props.worker.outputFileSizeInGbytes < 1 ? parseFloat((this.props.worker.outputFileSizeInGbytes * 1000).toPrecision(4)) +" MB" : parseFloat((this.props.worker.outputFileSizeInGbytes).toPrecision(4)) + " GB")}

-

Estimated size

{this.props.worker.estSize == undefined ? 0 : (this.props.worker.estSize < 1 ? parseFloat((this.props.worker.estSize * 1000).toPrecision(4)) +" MB" : parseFloat((this.props.worker.estSize).toPrecision(4)) + " GB")}

- - - +
- -
- {'\u00A0'} +

Output file size:

+

{this.props.worker.outputFileSizeInGbytes == undefined ? 0 : (this.props.worker.outputFileSizeInGbytes < 1 ? parseFloat((this.props.worker.outputFileSizeInGbytes * 1000).toPrecision(4)) + " MB" : parseFloat((this.props.worker.outputFileSizeInGbytes).toPrecision(4)) + " GB")}

-
+ +
+ {'\u00A0'} -}} >Shutdown worker +
+ + Meteor.call('killWorker', this.props.worker._id, this.props.worker.file, this.props.worker.mode, function (error, result) { }) + + + }} >Shutdown worker + + diff --git a/private/fileScanner/fileScanner.js b/private/fileScanner/fileScanner.js index 8692c834..8e87c19a 100644 --- a/private/fileScanner/fileScanner.js +++ b/private/fileScanner/fileScanner.js @@ -577,7 +577,12 @@ function ffprobeLaunch(filesToScan) { } catch (err) { } try { - var bit_rate = (8 * singleFileSize) / parseFloat(thisFileObject.ffProbeData.streams[0]["duration"]) + if (typeof thisFileObject.meta.Duration != 'undefined') { + var bit_rate = (8 * singleFileSize) / parseFloat(thisFileObject.meta.Duration) + } else { + var bit_rate = (8 * singleFileSize) / parseFloat(thisFileObject.ffProbeData.streams[0]["duration"]) + } + thisFileObject.bit_rate = bit_rate } catch (err) { diff --git a/server/main.js b/server/main.js index 96213ba6..3c642a59 100644 --- a/server/main.js +++ b/server/main.js @@ -48,7 +48,6 @@ var runningScans = [] var workerDB = [] var filesToAddToDB = [] -var logsToAddToDB = [] //__dirname = getRootDir() @@ -711,11 +710,12 @@ function main() { - process.on('uncaughtException', function (err) { - console.error(err.stack); + process.on('uncaughtException', Meteor.bindEnvironment(function (err) { + console.log('Error in main thread:'+err) + updateConsole('Error in main thread:'+err, false) + + })); - // process.exit(); - }); @@ -2116,6 +2116,9 @@ function main() { updateConsole(`Add file to DB request received for: ${jsonData._id}. Queueing`, true) + + + filesToAddToDB.push(jsonData) @@ -3950,55 +3953,19 @@ function main() { function updateConsole(message, skipWrite) { - //console.log(skipWrite) if (verboseLogs == true) { skipWrite = false } - //console.log(skipWrite) if (skipWrite == false) { - - console.log(`Server: ${message}`) - - var _id = shortid.generate() - var a1 = message - // var a2 = process.memoryUsage() - // var a3 = (os.totalmem()-os.freemem())/1000 - // var a4 =(os.freemem())/1000 - // var a5 = (v*100) - var a6 = new Date() - - var temp = { - - _id: _id, - text: a1, - // nodeMem:a2, - // systemUsedMem:a3, - // systemFreeMem:a4, - // systemCPUPercentage:a5, - createdAt: a6, - + try { + fs.appendFileSync(homePath + "/Tdarr/Logs/log.txt", getDateNow() + ":" + message + '\n', 'utf8'); + } catch (err) { + console.log(err.stack) } - - logsToAddToDB.push(temp) - - } - - - - - - - - - // os.cpuUsage( Meteor.bindEnvironment(function(v){ - // })); - - - } @@ -4224,18 +4191,39 @@ function main() { } else { + try { + var tempObj = filesToAddToDB[i] - try { + //if exact file already exists in DB then do nothing + //else remove existing item and insert + var existingFile = FileDB.findOne({ _id: filesToAddToDB[i]._id }); - updateConsole(`Adding file to DB: ${filesToAddToDB[i]._id}`, true) + if (existingFile == undefined) { + updateConsole("This exact file does not exist in DB. Adding", true) + Meteor.call('modifyFileDB', 'insert', filesToAddToDB[i]._id, tempObj, (error, result) => { }) + updateConsole(`Adding file to DB: ${filesToAddToDB[i]._id}`, true) + } else { - var tempObj = filesToAddToDB[i] - Meteor.call('modifyFileDB', 'upsert', filesToAddToDB[i]._id, tempObj, (error, result) => { }) + //compare modified time and bitrate + var mtime_new = filesToAddToDB[i].statSync.mtimeMs + var mtime_old = existingFile.statSync.mtimeMs + var br_new = filesToAddToDB[i].bit_rate + var br_old = existingFile.bit_rate + if (mtime_new == mtime_old && br_new == br_old) { + console.log("This exact file already exists in DB.") + + } else { + updateConsole("This exact file does not exist in DB. Removing old, adding new", true) + Meteor.call('modifyFileDB', 'removeOne', filesToAddToDB[i]._id, (error, result) => { }) + Meteor.call('modifyFileDB', 'insert', filesToAddToDB[i]._id, tempObj, (error, result) => { }) + updateConsole(`Adding file to DB: ${filesToAddToDB[i]._id}`, true) + } + } } catch (err) { console.log(err.stack) @@ -4251,44 +4239,6 @@ function main() { } - - for (var i = 0; i < logsToAddToDB.length; i++) { - - if (addFilesToDB == false) { - - break - - } else { - try { - - - // updateConsole(`Adding log to DB: ${logsToAddToDB[i].text}`,true) - - //123 - - // LogDB.upsert(logsToAddToDB[i]._id, - // { - // $set: logsToAddToDB[i] - // } - - // ); - - fs.appendFileSync(homePath + "/Tdarr/Logs/log.txt", getDateNow() + ":" + logsToAddToDB[i].text + '\n', 'utf8'); - - - - } catch (err) { - console.log(err.stack) - - - } - - logsToAddToDB.splice(i, 1) - - i-- - - } - } } catch (err) { console.log(err.stack) } @@ -4710,7 +4660,7 @@ function main() { statisticsUpdate(); - filesToAddToDBLengthNew = filesToAddToDB.length + logsToAddToDB.length + filesToAddToDBLengthNew = filesToAddToDB.length var DBLoadStatus @@ -4740,14 +4690,14 @@ function main() { // } } - DBPollPeriod = allFilesPulledTable.length + filesToAddToDB.length + logsToAddToDB.length + DBPollPeriod = allFilesPulledTable.length + filesToAddToDB.length //console.log("DBPollPeriod:" + DBPollPeriod) oldFetchtime = newFetchtime - filesToAddToDBLengthOld = filesToAddToDB.length + logsToAddToDB.length + filesToAddToDBLengthOld = filesToAddToDB.length StatisticsDB.upsert("statistics", @@ -4757,7 +4707,7 @@ function main() { DBFetchTime: (newFetchtime).toFixed(1) + "s", DBTotalTime: ((DBPollPeriod > 1000 ? (DBPollPeriod / 1000) : 1) + newFetchtime).toFixed(1) + "s", DBLoadStatus: DBLoadStatus, - DBQueue: filesToAddToDB.length + logsToAddToDB.length + DBQueue: filesToAddToDB.length } } ); @@ -4947,8 +4897,8 @@ function main() { if (process.platform == 'win32') { - var workerCommandFFmpeg = 'wmic process where name=\"ffmpeg.exe\" CALL setpriority \"Below normal\"' - var workerCommandHandBrake = 'wmic process where name=\"HandBrakeCLI.exe\" CALL setpriority \"Below normal\"' + var workerCommandFFmpeg = 'wmic process where name=\"ffmpeg.exe\" CALL setpriority \"Low\"' + var workerCommandHandBrake = 'wmic process where name=\"HandBrakeCLI.exe\" CALL setpriority \"Low\"' } @@ -4997,7 +4947,7 @@ function main() { //worker will cancel item if percentage stays the same for 300 secs function workerUpdateCheck() { - + try { @@ -5136,7 +5086,7 @@ function main() { } catch (err) { console.log(err.stack) } - setTimeout(Meteor.bindEnvironment(workerUpdateCheck), 1000); + setTimeout(Meteor.bindEnvironment(workerUpdateCheck), 3000); } function removeFromProcessing(file) { @@ -5197,4 +5147,4 @@ function main() { }); initialising = false; -} +} \ No newline at end of file