node-red-contrib-hik-media-buffer 1.1.91 → 1.1.92

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.
@@ -183,7 +183,6 @@ module.exports = function(RED) {
183
183
  const rawUri = uriMatch[1].replace(/&/g, '&');
184
184
  const downXml = `<?xml version="1.0" encoding="UTF-8"?><downloadRequest><playbackURI>${rawUri.replace(/&/g, '&amp;')}</playbackURI></downloadRequest>`.trim();
185
185
 
186
- // Facciamo lo stesso giochetto del file temporaneo anche per il download
187
186
  const tempDownXmlPath = path.join(baseStorage, `down_${t.id}_${timestamp}.xml`);
188
187
  fs.writeFileSync(tempDownXmlPath, downXml, 'utf8');
189
188
 
@@ -194,12 +193,11 @@ module.exports = function(RED) {
194
193
  const downUrl = `${node.protocol}://${node.host}:${node.port}/ISAPI/ContentMgmt/download`;
195
194
  const curlDownCommand = `curl -s -X POST --digest -u "${node.user}:${node.pass}" -H "Content-Type: application/xml; charset=UTF-8" -d "@${tempDownXmlPath}" "${downUrl}" -o "${targetFilePath}"`;
196
195
 
197
- node.warn(`[DEBUG] Eseguo download traccia ${t.id} tramite cURL via file temporaneo...`);
196
+ node.warn(`[DEBUG] Eseguo download traccia ${t.id} tramite cURL...`);
198
197
  await new Promise((resolve) => {
199
198
  exec(curlDownCommand, () => resolve());
200
199
  });
201
200
 
202
- // Cancelliamo il file XML del download
203
201
  try { if (fs.existsSync(tempDownXmlPath)) fs.unlinkSync(tempDownXmlPath); } catch(e){}
204
202
 
205
203
  if (fs.existsSync(targetFilePath) && fs.statSync(targetFilePath).size > 0) {
@@ -208,18 +206,31 @@ module.exports = function(RED) {
208
206
  fileDaCancellare.push(fullImgPath);
209
207
  } else {
210
208
  const fixedPath = path.join(baseStorage, `hik_v_${channelID}_${timestamp}.mp4`);
211
- let videoBuffer = fs.readFileSync(rawPath);
212
- if (videoBuffer.slice(0, 4).toString() === 'IMKH') {
213
- try { fs.writeFileSync(rawPath, videoBuffer.slice(40)); } catch(e){}
209
+
210
+ // Tagliamo via l'header proprietario IMKH se presente
211
+ let fileStats = fs.statSync(rawPath);
212
+ if (fileStats.size > 40) {
213
+ let fd = fs.openSync(rawPath, 'r');
214
+ let magicBuffer = Buffer.alloc(4);
215
+ fs.readSync(fd, magicBuffer, 0, 4, 0);
216
+ fs.closeSync(fd);
217
+
218
+ if (magicBuffer.toString() === 'IMKH') {
219
+ // Taglio dell'header senza leggere tutto in memoria (evita crash su file giganti)
220
+ exec(`ffmpeg -y -ss 00:00:00 -i "${rawPath}" -c copy -map 0 -an "${fixedPath}"`, () => {});
221
+ }
214
222
  }
215
223
 
224
+ node.warn(`[DEBUG] Ritaglio il video dell'evento a 10 secondi per non saturare la memoria...`);
225
+ // USIAMO FFMPEG PER PRENDERE SOLO GLI ULTIMI 10 SECONDI ED EVITARE IL FILE DA 1GB IN BASE64
216
226
  await new Promise((resolve) => {
217
- exec(`ffmpeg -y -i "${rawPath}" -c copy -movflags +faststart "${fixedPath}"`, (err) => {
218
- if (!err && fs.existsSync(fixedPath)) {
227
+ exec(`ffmpeg -y -sseof -10 -i "${rawPath}" -c copy -movflags +faststart "${fixedPath}"`, (err) => {
228
+ if (!err && fs.existsSync(fixedPath) && fs.statSync(fixedPath).size > 0) {
229
+ // Leggiamo il file tagliato che ora peserà pochissimo!
219
230
  output.video_base64 = fs.readFileSync(fixedPath, { encoding: 'base64' });
220
231
  fileDaCancellare.push(fixedPath);
221
232
  } else {
222
- output.video_base64 = fs.readFileSync(rawPath, { encoding: 'base64' });
233
+ node.error(`[DEBUG FFMPEG] Impossibile tagliare il video, traccia troppo pesante.`);
223
234
  }
224
235
  fileDaCancellare.push(rawPath);
225
236
  resolve();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-hik-media-buffer",
3
- "version": "1.1.91",
3
+ "version": "1.1.92",
4
4
  "description": "Ottiene buffer video e immagine da camere Hikvision via ISAPI",
5
5
  "keywords": [
6
6
  "node-red",