orator-conversion 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/debug/Harness.js
CHANGED
|
@@ -1,10 +1,48 @@
|
|
|
1
1
|
const libFable = require('fable');
|
|
2
|
+
const libPath = require('path');
|
|
3
|
+
|
|
4
|
+
// Parse command-line flags before creating Fable so LogStreams can be set
|
|
5
|
+
let tmpUltravisorURL = null;
|
|
6
|
+
let tmpLogFilePath = null;
|
|
7
|
+
for (let i = 2; i < process.argv.length; i++)
|
|
8
|
+
{
|
|
9
|
+
if ((process.argv[i] === '--ultravisor' || process.argv[i] === '-u'))
|
|
10
|
+
{
|
|
11
|
+
if (process.argv[i + 1] && !process.argv[i + 1].startsWith('-'))
|
|
12
|
+
{
|
|
13
|
+
tmpUltravisorURL = process.argv[++i];
|
|
14
|
+
}
|
|
15
|
+
else
|
|
16
|
+
{
|
|
17
|
+
tmpUltravisorURL = 'http://localhost:54321';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (process.argv[i] === '--logfile' || process.argv[i] === '-l')
|
|
21
|
+
{
|
|
22
|
+
if (process.argv[i + 1] && !process.argv[i + 1].startsWith('-'))
|
|
23
|
+
{
|
|
24
|
+
tmpLogFilePath = libPath.resolve(process.argv[++i]);
|
|
25
|
+
}
|
|
26
|
+
else
|
|
27
|
+
{
|
|
28
|
+
tmpLogFilePath = libPath.resolve(`orator-conversion-${new Date().toISOString().replace(/[:.]/g, '-')}.log`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let tmpLogStreams = [{ level: 'trace', streamtype: 'process.stdout' }];
|
|
34
|
+
if (tmpLogFilePath)
|
|
35
|
+
{
|
|
36
|
+
tmpLogStreams.push({ loggertype: 'simpleflatfile', level: 'trace', path: tmpLogFilePath });
|
|
37
|
+
console.log(`[Orator-Conversion] Logging to file: ${tmpLogFilePath}`);
|
|
38
|
+
}
|
|
2
39
|
|
|
3
40
|
const defaultFableSettings = (
|
|
4
41
|
{
|
|
5
42
|
Product: 'Orator-FileTranslation',
|
|
6
43
|
ProductVersion: '1.0.0',
|
|
7
|
-
APIServerPort: 8765
|
|
44
|
+
APIServerPort: 8765,
|
|
45
|
+
LogStreams: tmpLogStreams
|
|
8
46
|
});
|
|
9
47
|
|
|
10
48
|
let _Fable = new libFable(defaultFableSettings);
|
|
@@ -32,6 +70,30 @@ tmpAnticipate.anticipate(
|
|
|
32
70
|
|
|
33
71
|
tmpAnticipate.anticipate(_Orator.startService.bind(_Orator));
|
|
34
72
|
|
|
73
|
+
// If an Ultravisor URL was provided, connect as a beacon
|
|
74
|
+
if (tmpUltravisorURL)
|
|
75
|
+
{
|
|
76
|
+
tmpAnticipate.anticipate(
|
|
77
|
+
(fNext) =>
|
|
78
|
+
{
|
|
79
|
+
_Fable.OratorFileTranslation.connectBeacon(
|
|
80
|
+
{
|
|
81
|
+
ServerURL: tmpUltravisorURL,
|
|
82
|
+
Name: 'orator-conversion',
|
|
83
|
+
BindAddresses: [{ IP: '127.0.0.1', Port: 8765, Protocol: 'http' }]
|
|
84
|
+
},
|
|
85
|
+
(pError) =>
|
|
86
|
+
{
|
|
87
|
+
if (pError)
|
|
88
|
+
{
|
|
89
|
+
_Fable.log.warn(`Beacon connection failed (server may not be running): ${pError.message}`);
|
|
90
|
+
_Fable.log.warn('HTTP endpoints are still available. Beacon will not be active.');
|
|
91
|
+
}
|
|
92
|
+
return fNext();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
35
97
|
tmpAnticipate.wait(
|
|
36
98
|
(pError) =>
|
|
37
99
|
{
|
|
@@ -45,4 +107,27 @@ tmpAnticipate.wait(
|
|
|
45
107
|
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/image/png-to-jpg');
|
|
46
108
|
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/pdf-to-page-png/:Page');
|
|
47
109
|
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/pdf-to-page-jpg/:Page');
|
|
110
|
+
|
|
111
|
+
if (tmpUltravisorURL)
|
|
112
|
+
{
|
|
113
|
+
_Fable.log.info('');
|
|
114
|
+
_Fable.log.info(`Beacon: connected to Ultravisor at ${tmpUltravisorURL}`);
|
|
115
|
+
}
|
|
48
116
|
});
|
|
117
|
+
|
|
118
|
+
// Graceful shutdown
|
|
119
|
+
process.on('SIGINT', () =>
|
|
120
|
+
{
|
|
121
|
+
console.log('\n[Orator-Conversion] Shutting down...');
|
|
122
|
+
if (_Fable.OratorFileTranslation._BeaconService)
|
|
123
|
+
{
|
|
124
|
+
_Fable.OratorFileTranslation.disconnectBeacon(() =>
|
|
125
|
+
{
|
|
126
|
+
process.exit(0);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
else
|
|
130
|
+
{
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orator-conversion",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "File format conversion endpoints for Orator service servers.",
|
|
5
5
|
"main": "source/Orator-File-Translation.js",
|
|
6
6
|
"scripts": {
|
|
@@ -42,7 +42,9 @@
|
|
|
42
42
|
"homepage": "https://github.com/stevenvelozo/orator-conversion#readme",
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"fable-serviceproviderbase": "^3.0.19",
|
|
45
|
-
"sharp": "^0.34.5"
|
|
45
|
+
"sharp": "^0.34.5",
|
|
46
|
+
"ultravisor-beacon": "^0.0.3",
|
|
47
|
+
"ws": "^8.20.0"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
50
|
"fable": "^3.1.67",
|
|
@@ -94,9 +94,9 @@ class ConversionCore
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
* Resize an image
|
|
97
|
+
* Resize an image with Sharp.
|
|
98
98
|
*
|
|
99
|
-
* @param {Buffer}
|
|
99
|
+
* @param {Buffer|string} pInput - Image data (Buffer) or file path (string).
|
|
100
100
|
* @param {object} pOptions - Resize options.
|
|
101
101
|
* @param {number} [pOptions.Width] - Target width in pixels.
|
|
102
102
|
* @param {number} [pOptions.Height] - Target height in pixels.
|
|
@@ -107,7 +107,7 @@ class ConversionCore
|
|
|
107
107
|
* @param {string} [pOptions.Position] - Resize position/gravity: 'centre', 'north', 'south', etc.
|
|
108
108
|
* @param {Function} fCallback - Called with (pError, pOutputBuffer, pContentType).
|
|
109
109
|
*/
|
|
110
|
-
imageResize(
|
|
110
|
+
imageResize(pInput, pOptions, fCallback)
|
|
111
111
|
{
|
|
112
112
|
let tmpOptions = pOptions || {};
|
|
113
113
|
let tmpFormat = (tmpOptions.Format || 'jpeg').toLowerCase();
|
|
@@ -132,7 +132,8 @@ class ConversionCore
|
|
|
132
132
|
tmpResizeConfig.position = tmpOptions.Position;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
// Accept file path or buffer; disable pixel limit for large scans
|
|
136
|
+
let tmpSharpInstance = libSharp(pInput, { limitInputPixels: false });
|
|
136
137
|
|
|
137
138
|
if (tmpAutoOrient)
|
|
138
139
|
{
|
|
@@ -268,9 +268,33 @@ class OratorConversionBeaconProvider extends libBeaconCapabilityProvider
|
|
|
268
268
|
*/
|
|
269
269
|
execute(pAction, pWorkItem, pContext, fCallback, fReportProgress)
|
|
270
270
|
{
|
|
271
|
+
let tmpLog = pContext && pContext.log ? pContext.log : { info: console.log, warn: console.warn, error: console.error };
|
|
272
|
+
tmpLog.info(`[OratorConversion] execute: action="${pAction}" workItem=${pWorkItem.WorkItemHash || '?'} settings=${JSON.stringify(pWorkItem.Settings || {}).substring(0, 200)}`);
|
|
271
273
|
let tmpSettings = pWorkItem.Settings || {};
|
|
272
274
|
let tmpStagingPath = pContext.StagingPath || process.cwd();
|
|
273
275
|
|
|
276
|
+
// Coerce settings types from the action's schema.
|
|
277
|
+
// Template engines and JSON transport may deliver numbers as strings.
|
|
278
|
+
let tmpActionDef = this.actions[pAction];
|
|
279
|
+
if (tmpActionDef && tmpActionDef.SettingsSchema)
|
|
280
|
+
{
|
|
281
|
+
for (let i = 0; i < tmpActionDef.SettingsSchema.length; i++)
|
|
282
|
+
{
|
|
283
|
+
let tmpField = tmpActionDef.SettingsSchema[i];
|
|
284
|
+
let tmpVal = tmpSettings[tmpField.Name];
|
|
285
|
+
if (tmpVal === undefined || tmpVal === null || tmpVal === '') { continue; }
|
|
286
|
+
if (tmpField.DataType === 'Number' && typeof tmpVal === 'string')
|
|
287
|
+
{
|
|
288
|
+
let tmpNum = Number(tmpVal);
|
|
289
|
+
if (!isNaN(tmpNum)) { tmpSettings[tmpField.Name] = tmpNum; }
|
|
290
|
+
}
|
|
291
|
+
else if (tmpField.DataType === 'Boolean' && typeof tmpVal === 'string')
|
|
292
|
+
{
|
|
293
|
+
tmpSettings[tmpField.Name] = (tmpVal === 'true' || tmpVal === '1');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
274
298
|
let tmpInputPath = this._resolvePath(tmpSettings.InputFile, tmpStagingPath);
|
|
275
299
|
let tmpOutputPath = this._resolvePath(tmpSettings.OutputFile, tmpStagingPath);
|
|
276
300
|
|
|
@@ -284,14 +308,17 @@ class OratorConversionBeaconProvider extends libBeaconCapabilityProvider
|
|
|
284
308
|
|
|
285
309
|
if (!libFS.existsSync(tmpInputPath))
|
|
286
310
|
{
|
|
311
|
+
tmpLog.warn(`[OratorConversion] Input file NOT FOUND: ${tmpInputPath} (settings.InputFile=${tmpSettings.InputFile})`);
|
|
287
312
|
return fCallback(null, {
|
|
288
313
|
Outputs: { StdOut: `Input file not found: ${tmpSettings.InputFile}`, ExitCode: -1, Result: '' },
|
|
289
314
|
Log: [`OratorConversion: input file not found: ${tmpInputPath}`]
|
|
290
315
|
});
|
|
291
316
|
}
|
|
292
317
|
|
|
293
|
-
|
|
294
|
-
|
|
318
|
+
tmpLog.info(`[OratorConversion] Input file OK: ${tmpInputPath} (${libFS.statSync(tmpInputPath).size} bytes)`);
|
|
319
|
+
|
|
320
|
+
// File-path actions skip the buffer read — Sharp and ffmpeg handle files directly
|
|
321
|
+
let tmpFilePathActions = { 'ImageResize': true, 'ImageConvert': true, 'MediaProbe': true, 'VideoExtractFrame': true, 'VideoThumbnail': true, 'AudioExtractSegment': true, 'AudioWaveform': true };
|
|
295
322
|
if (tmpFilePathActions[pAction])
|
|
296
323
|
{
|
|
297
324
|
return this._executeFilePathAction(pAction, tmpSettings, tmpInputPath, tmpOutputPath, fCallback, fReportProgress);
|
|
@@ -325,12 +352,15 @@ class OratorConversionBeaconProvider extends libBeaconCapabilityProvider
|
|
|
325
352
|
{
|
|
326
353
|
if (pError)
|
|
327
354
|
{
|
|
355
|
+
tmpLog.error(`[OratorConversion] ${pAction} FAILED: ${pError.message}`);
|
|
328
356
|
return fCallback(null, {
|
|
329
357
|
Outputs: { StdOut: `Conversion failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
330
358
|
Log: [`OratorConversion ${pAction} error: ${pError.message}`]
|
|
331
359
|
});
|
|
332
360
|
}
|
|
333
361
|
|
|
362
|
+
tmpLog.info(`[OratorConversion] ${pAction} SUCCESS: ${pOutputBuffer.length} bytes → ${tmpOutputPath}`);
|
|
363
|
+
|
|
334
364
|
try
|
|
335
365
|
{
|
|
336
366
|
libFS.writeFileSync(tmpOutputPath, pOutputBuffer);
|
|
@@ -697,6 +727,102 @@ class OratorConversionBeaconProvider extends libBeaconCapabilityProvider
|
|
|
697
727
|
break;
|
|
698
728
|
}
|
|
699
729
|
|
|
730
|
+
case 'ImageResize':
|
|
731
|
+
{
|
|
732
|
+
if (fReportProgress) fReportProgress({ Percent: 10, Message: 'Resizing image...' });
|
|
733
|
+
this._Core.imageResize(pInputPath,
|
|
734
|
+
{
|
|
735
|
+
Width: pSettings.Width,
|
|
736
|
+
Height: pSettings.Height,
|
|
737
|
+
Format: pSettings.Format,
|
|
738
|
+
Quality: pSettings.Quality,
|
|
739
|
+
AutoOrient: pSettings.AutoOrient,
|
|
740
|
+
Fit: pSettings.Fit,
|
|
741
|
+
Position: pSettings.Position
|
|
742
|
+
},
|
|
743
|
+
(pError, pOutputBuffer, pContentType) =>
|
|
744
|
+
{
|
|
745
|
+
if (pError)
|
|
746
|
+
{
|
|
747
|
+
return fCallback(null, {
|
|
748
|
+
Outputs: { StdOut: `Resize failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
749
|
+
Log: [`OratorConversion ImageResize error: ${pError.message}`]
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
try
|
|
754
|
+
{
|
|
755
|
+
libFS.writeFileSync(pOutputPath, pOutputBuffer);
|
|
756
|
+
}
|
|
757
|
+
catch (pWriteError)
|
|
758
|
+
{
|
|
759
|
+
return fCallback(null, {
|
|
760
|
+
Outputs: { StdOut: `Write failed: ${pWriteError.message}`, ExitCode: 1, Result: '' },
|
|
761
|
+
Log: [`OratorConversion ImageResize write error: ${pWriteError.message}`]
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return fCallback(null, {
|
|
766
|
+
Outputs:
|
|
767
|
+
{
|
|
768
|
+
StdOut: `Resized ${pSettings.InputFile} → ${pSettings.OutputFile}`,
|
|
769
|
+
ExitCode: 0,
|
|
770
|
+
Result: pOutputPath,
|
|
771
|
+
ContentType: pContentType || '',
|
|
772
|
+
OutputSize: pOutputBuffer.length
|
|
773
|
+
},
|
|
774
|
+
Log: [`OratorConversion ImageResize: ${pSettings.InputFile} → ${pSettings.OutputFile} (${pOutputBuffer.length} bytes)`]
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
break;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
case 'ImageConvert':
|
|
781
|
+
{
|
|
782
|
+
if (fReportProgress) fReportProgress({ Percent: 10, Message: 'Converting image...' });
|
|
783
|
+
this._Core.imageResize(pInputPath,
|
|
784
|
+
{
|
|
785
|
+
Format: pSettings.Format,
|
|
786
|
+
Quality: pSettings.Quality,
|
|
787
|
+
AutoOrient: pSettings.AutoOrient
|
|
788
|
+
},
|
|
789
|
+
(pError, pOutputBuffer, pContentType) =>
|
|
790
|
+
{
|
|
791
|
+
if (pError)
|
|
792
|
+
{
|
|
793
|
+
return fCallback(null, {
|
|
794
|
+
Outputs: { StdOut: `Convert failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
795
|
+
Log: [`OratorConversion ImageConvert error: ${pError.message}`]
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
try
|
|
800
|
+
{
|
|
801
|
+
libFS.writeFileSync(pOutputPath, pOutputBuffer);
|
|
802
|
+
}
|
|
803
|
+
catch (pWriteError)
|
|
804
|
+
{
|
|
805
|
+
return fCallback(null, {
|
|
806
|
+
Outputs: { StdOut: `Write failed: ${pWriteError.message}`, ExitCode: 1, Result: '' },
|
|
807
|
+
Log: [`OratorConversion ImageConvert write error: ${pWriteError.message}`]
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
return fCallback(null, {
|
|
812
|
+
Outputs:
|
|
813
|
+
{
|
|
814
|
+
StdOut: `Converted ${pSettings.InputFile} → ${pSettings.OutputFile}`,
|
|
815
|
+
ExitCode: 0,
|
|
816
|
+
Result: pOutputPath,
|
|
817
|
+
ContentType: pContentType || '',
|
|
818
|
+
OutputSize: pOutputBuffer.length
|
|
819
|
+
},
|
|
820
|
+
Log: [`OratorConversion ImageConvert: ${pSettings.InputFile} → ${pSettings.OutputFile} (${pOutputBuffer.length} bytes)`]
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
|
|
700
826
|
default:
|
|
701
827
|
return fCallback(null, {
|
|
702
828
|
Outputs: { StdOut: `Unknown file-path action: ${pAction}`, ExitCode: -1, Result: '' },
|
|
@@ -6,6 +6,9 @@ const libFS = require('fs');
|
|
|
6
6
|
const libPath = require('path');
|
|
7
7
|
const libOS = require('os');
|
|
8
8
|
|
|
9
|
+
const libBeaconService = require('ultravisor-beacon');
|
|
10
|
+
const libOratorConversionBeaconProvider = require('./Orator-Conversion-BeaconProvider.js');
|
|
11
|
+
|
|
9
12
|
const libEndpointImageJpgToPng = require('./endpoints/Endpoint-Image-JpgToPng.js');
|
|
10
13
|
const libEndpointImagePngToJpg = require('./endpoints/Endpoint-Image-PngToJpg.js');
|
|
11
14
|
const libEndpointImageResize = require('./endpoints/Endpoint-Image-Resize.js');
|
|
@@ -78,6 +81,9 @@ class OratorFileTranslation extends libFableServiceProviderBase
|
|
|
78
81
|
// Array of instantiated endpoint services
|
|
79
82
|
this._endpointServices = [];
|
|
80
83
|
|
|
84
|
+
// Beacon service reference (created on connectBeacon)
|
|
85
|
+
this._BeaconService = null;
|
|
86
|
+
|
|
81
87
|
// Initialize the built-in converters
|
|
82
88
|
this.initializeDefaultConverters();
|
|
83
89
|
}
|
|
@@ -508,6 +514,145 @@ class OratorFileTranslation extends libFableServiceProviderBase
|
|
|
508
514
|
|
|
509
515
|
return true;
|
|
510
516
|
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Connect to an Ultravisor coordinator as a beacon, exposing the same
|
|
520
|
+
* MediaConversion capabilities available through the HTTP endpoints.
|
|
521
|
+
*
|
|
522
|
+
* This makes the running orator-conversion server discoverable by
|
|
523
|
+
* Ultravisor and allows it to receive work items from the mesh.
|
|
524
|
+
*
|
|
525
|
+
* @param {object} pBeaconConfig Beacon configuration:
|
|
526
|
+
* - ServerURL {string} Ultravisor server URL (required)
|
|
527
|
+
* - Name {string} Beacon name (default: 'orator-conversion')
|
|
528
|
+
* - Password {string} Auth password (default: '')
|
|
529
|
+
* - MaxConcurrent {number} Max concurrent work items (default: 2)
|
|
530
|
+
* - StagingPath {string} Local staging directory (default: cwd)
|
|
531
|
+
* - Tags {object} Beacon tags (default: {})
|
|
532
|
+
* @param {Function} fCallback Called with (pError, pBeaconInfo)
|
|
533
|
+
*/
|
|
534
|
+
connectBeacon(pBeaconConfig, fCallback)
|
|
535
|
+
{
|
|
536
|
+
if (!pBeaconConfig || !pBeaconConfig.ServerURL)
|
|
537
|
+
{
|
|
538
|
+
return fCallback(new Error('connectBeacon requires a ServerURL in the config.'));
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (this._BeaconService && this._BeaconService.isEnabled())
|
|
542
|
+
{
|
|
543
|
+
this.log.warn('OratorFileTranslation: beacon already connected.');
|
|
544
|
+
return fCallback(null);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Register the beacon service type with fable if not already present
|
|
548
|
+
this.fable.addServiceTypeIfNotExists('UltravisorBeacon', libBeaconService);
|
|
549
|
+
|
|
550
|
+
// Default staging path to dist/orator-conversion-staging
|
|
551
|
+
let tmpStagingPath = pBeaconConfig.StagingPath || require('path').resolve(__dirname, '..', 'dist', 'orator-conversion-staging');
|
|
552
|
+
|
|
553
|
+
// Ensure staging directory exists
|
|
554
|
+
try
|
|
555
|
+
{
|
|
556
|
+
require('fs').mkdirSync(tmpStagingPath, { recursive: true });
|
|
557
|
+
}
|
|
558
|
+
catch (pMkdirError)
|
|
559
|
+
{
|
|
560
|
+
// Already exists — fine
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Instantiate the beacon service with the provided config
|
|
564
|
+
this._BeaconService = this.fable.instantiateServiceProviderWithoutRegistration('UltravisorBeacon',
|
|
565
|
+
{
|
|
566
|
+
ServerURL: pBeaconConfig.ServerURL,
|
|
567
|
+
Name: pBeaconConfig.Name || 'orator-conversion',
|
|
568
|
+
Password: pBeaconConfig.Password || '',
|
|
569
|
+
MaxConcurrent: pBeaconConfig.MaxConcurrent || 2,
|
|
570
|
+
StagingPath: tmpStagingPath,
|
|
571
|
+
Tags: pBeaconConfig.Tags || {},
|
|
572
|
+
BindAddresses: pBeaconConfig.BindAddresses || []
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// Create the MediaConversion capability provider and register it
|
|
576
|
+
let tmpProvider = new libOratorConversionBeaconProvider(
|
|
577
|
+
{
|
|
578
|
+
PdftkPath: this.PdftkPath,
|
|
579
|
+
PdftoppmPath: this.PdftoppmPath,
|
|
580
|
+
FfmpegPath: pBeaconConfig.FfmpegPath || 'ffmpeg',
|
|
581
|
+
FfprobePath: pBeaconConfig.FfprobePath || 'ffprobe',
|
|
582
|
+
MaxFileSizeBytes: this.MaxFileSize,
|
|
583
|
+
LogLevel: this.LogLevel
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
// Initialize the provider (checks tool availability), then register and enable
|
|
587
|
+
tmpProvider.initialize(
|
|
588
|
+
(pInitError) =>
|
|
589
|
+
{
|
|
590
|
+
if (pInitError)
|
|
591
|
+
{
|
|
592
|
+
this.log.error(`OratorFileTranslation: beacon provider init failed: ${pInitError.message}`);
|
|
593
|
+
this._BeaconService = null;
|
|
594
|
+
return fCallback(pInitError);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Register the capability with the beacon service
|
|
598
|
+
this._BeaconService.registerCapability(
|
|
599
|
+
{
|
|
600
|
+
Capability: tmpProvider.Capability,
|
|
601
|
+
Name: tmpProvider.Name,
|
|
602
|
+
actions: tmpProvider.actions,
|
|
603
|
+
execute: tmpProvider.execute.bind(tmpProvider),
|
|
604
|
+
initialize: (fCb) => { return fCb(null); }, // Already initialized above
|
|
605
|
+
shutdown: (fCb) => { return fCb(null); }
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
// Enable the beacon — authenticate, register, begin polling
|
|
609
|
+
this._BeaconService.enable(
|
|
610
|
+
(pEnableError, pBeaconInfo) =>
|
|
611
|
+
{
|
|
612
|
+
if (pEnableError)
|
|
613
|
+
{
|
|
614
|
+
this.log.error(`OratorFileTranslation: beacon enable failed: ${pEnableError.message}`);
|
|
615
|
+
this._BeaconService = null;
|
|
616
|
+
return fCallback(pEnableError);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
this.log.info(`OratorFileTranslation: beacon connected as ${pBeaconInfo.BeaconID}`);
|
|
620
|
+
return fCallback(null, pBeaconInfo);
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Disconnect the beacon from the Ultravisor coordinator.
|
|
627
|
+
*
|
|
628
|
+
* @param {Function} fCallback Called with (pError)
|
|
629
|
+
*/
|
|
630
|
+
disconnectBeacon(fCallback)
|
|
631
|
+
{
|
|
632
|
+
if (!this._BeaconService || !this._BeaconService.isEnabled())
|
|
633
|
+
{
|
|
634
|
+
if (this.log)
|
|
635
|
+
{
|
|
636
|
+
this.log.info('OratorFileTranslation: beacon not connected, nothing to disconnect.');
|
|
637
|
+
}
|
|
638
|
+
return fCallback(null);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
this._BeaconService.disable(
|
|
642
|
+
(pError) =>
|
|
643
|
+
{
|
|
644
|
+
if (pError)
|
|
645
|
+
{
|
|
646
|
+
this.log.warn(`OratorFileTranslation: beacon disconnect warning: ${pError.message}`);
|
|
647
|
+
}
|
|
648
|
+
else
|
|
649
|
+
{
|
|
650
|
+
this.log.info('OratorFileTranslation: beacon disconnected.');
|
|
651
|
+
}
|
|
652
|
+
this._BeaconService = null;
|
|
653
|
+
return fCallback(pError || null);
|
|
654
|
+
});
|
|
655
|
+
}
|
|
511
656
|
}
|
|
512
657
|
|
|
513
658
|
module.exports = OratorFileTranslation;
|