Tengo una aplicación Electron (con Angular).
Soy nuevo en Electron y todo este manejo de eventos entre procesos.
Mi problema es que tengo este controlador ipcMain (proceso principal) (que 'Invoco' desde un servicio Angular):
ipcMain.handle('video-audio-merge', (event, filename) => { return new Promise((resolve) => { new FFmpeg(filename+'.mp4').addInput(filename+'.mp3') .on('progress', progress => resolve(progress.percent)) // The problem is in this line .save('merged_'+filename+'.mp4') .on('end', () => resolve(100)); }); })Lo que estoy tratando de lograr es seguir el progreso de una combinación de un video y un audio (lo que puede llevar de varios segundos a varios minutos). Pero el problema aquí es que una vez que se resuelve la Promesa, no envía los siguientes valores de progreso (termino recibiendo el 3% y luego nunca recibo ningún otro valor, incluso si la 'fusión' todavía está en progreso).
Luego probé lo siguiente (proceso principal) (que no puedo compilar):
const Observable = require('rxjs'); ... ipcMain.handle('video-audio-merge', (event, filename) => { return new Promise((resolve) => { resolve( // Will resolve to an Observable that will be able to provide progress values new Observable<number>(subscriber => { new FFmpeg(filename+'.mp4').addInput(filename+'.mp3') .on('progress', progress => subscriber.next(progress.percent)) // Streaming progress values .save('merged_'+filename+'.mp4') .on('end', () => subscriber.completed()); }) // End Observable ); // End Resolve }); // End Promise }) // End ipcMain.handleAgregué comentarios para explicar lo que estoy tratando de lograr. Y en mi servicio Angular estoy invocando este controlador de la siguiente manera:
const electron = (<any>window).require('electron'); import { Observable } from 'rxjs'; ... electron.ipcRenderer.invoke('video-audio-merge', filename).then((subscriber: Observable<number>) => { // This should resolve to my Observable subscriber.subscribe((progress: number) => { // I subscribe to the Observable to get progress values console.log(progress); // here I should be using my progress value }); });Al compilar me sale el siguiente error:
A JavaScript error occurred in the main process Uncaught Exception: Error: Cannot find module 'rxjs-compat'Estoy convencido de que hay alguna otra forma 'elegante' de lograr este comportamiento entre los procesos Main y Renderer, si me puede guiar a alguno, se lo agradecería.
De lo contrario, ¿pueden ayudarme a resolver este error? o comparte conmigo qué puedo leer para aprender a usar 'Observables' en Electron.
Esta es la mejor manera que pude encontrar.
Comencemos con mi ipcMain (ver los comentarios del código):
ipcMain.on('video-audio-merge', (event, filename) => { new FFmpeg(filename+'.mp4').addInput(filename+'.mp3') .on('progress', (progress) => { event.reply(filename, { progress: progress.percent }); /* 'event.reply' as its name indicates sends a response through channel <filename>, which I use on the renderer process side to listen to progress value */ }) .save('./merged_'+filename+'.mp4'); }) // end ipcMain.onAsí es como construyo mi Observable en Angular (ver los comentarios del código):
VideoAudioMerge(filename: string) { return new Observable<any>(observer => { electron.ipcRenderer.on(filename, (event: any, data: any) => { /* Creates an ipcRenderer listener on channel named <filename>, so when multiple files are progressing at the same time each will send it's progress value on a different channel */ observer.next(data.progress); if(data.progress >= 100) observer.complete(); }); electron.ipcRenderer.send('video-audio-merge', filename); }); } // end VideoAudioMergeY finalmente, así es como uso el Observable (ver los comentarios del código):
this.VideoAudioMerge(filename).subscribe( progress => { this.progress = progress }, (error) => {/*Error handling */}, () => { electron.ipcRenderer.removeAllListeners(filename); // At the end of video merge remove each <filename> listener. })Por favor, siéntase libre si tiene algún comentario :)