Why my IPC communication doesn't work properly?

This's a simple video duration check program built with Electron. However, it doesn't work as expected; I also tried to use Electron IPC communication in others projects, but always fails. I can upload a video successfully and submit it, after that nothings happens, any errors or advices. Debugger shows nothing too. I built a new project from zero and have same issue. Path value is also not showed on console

main.js:

const electron = require('electron'),
app = electron.app,
BrowserWindow = electron.BrowserWindow
const ffmpeg = require('fluent-ffmpeg')
const ipc = require('electron').ipcMain

let mainWindow

app.on('ready', () => {
    mainWindow = new BrowserWindow({})
    mainWindow.loadFile('./index.html')
})

ipc.on('video:submit', (event, path) => {
    ffmpeg.ffprobe(path, (metadata) => {
        event.returnValue = metadata.format.duration
    })
})

index.html:

<html>
    <head>
    </head>
    <body>
        <form id="form">
            <h1>Video Info</h1>
            <div>
                <label>Select a video</label>
                <input type="file" accept="video/*" id="input">
            </div>
            <button type="submit" id="sb">Get info</button>
            <div id="result"></div>
        </form>
    </body>
    <script>
        require('./renderer.js')
    </script>
</html>

renderer.js:

const ipc = require('electron').ipcRenderer,

form = document.querySelector('#form')

let result = document.querySelector('#result')

console.log(path)

form.addEventListener('submit', () => {
    const path = document.querySelector('#input').files[0].path
    let reply = ipc.sendSync('video:submit', path)
    result.innerHTML = 'Video is' + reply + 'seconds!'
})

EDIT

I made some changes on main and renderer to use asynchronous send and reply. I don't get what I want, but after submit some content, it's name is replaced with "No file chosen". Path value stills not printed.

changes on main.js:

ipc.on('video:submit', (event, path) => {
    ffmpeg.ffprobe(path, (metadata) => {
        let duration = metadata.format.duration
        event.reply('duration', duration)
    })
})

changes on renderer.js:

form.addEventListener('submit', () => {
    const path = document.querySelector('#input').files[0].path
    ipc.on('duration', (event, duration) => {
        console.log(duration)
    })
    ipc.send('video:submit', path)
    result.innerHTML = 'Video is' + duration + 'seconds!'
})

Answers:

Answer

The code looks good but I guess the problem lies in your form submission. The page should be reloading on submit and it does not reach the IPC send call. Try preventing default action for the form.

form.addEventListener('submit', (e) => {
  e.preventDefault()
  const path = document.querySelector('#input').files[0].path
    ipc.on('duration', (event, duration) => {
        console.log(duration)
    })
   ipc.send('video:submit', path)
    result.innerHTML = 'Video is' + duration + 'seconds!'
  })
Answer

Solved! There were 3 main errors so I don't know what exactly happened. But here are they:

1 - ipc functions were made wrong way. This is the right one (asynchronous reply):

renderer.js:

ipc.on('duration', (event, duration) => {
    result.innerHTML = `Video is ${duration} seconds!`    
})
ipc.send('video:submit', path)

main.js:

ipc.on('video:submit', (event, path) => {
    ffmpeg.ffprobe(path, (err, metadata) => {
        let duration = metadata.format.duration
        console.log(duration)
        event.reply('duration', duration)
    })
 })

2 - DOM wasn't getting submit button or event so "addEventListiner" was getting null... I changed submit button to input button with same id then cheanged submit event to simple click event. I query selected the input button rather the form at all. That's what I get finally:

renderer.js:

const ipc = require('electron').ipcRenderer,

suBtn = document.querySelector('input#sb')

let result = document.querySelector('div#result')

suBtn.addEventListener('click', (event) => {
    event.preventDefault()
    const path = document.querySelector('input#file').files[0].path
    ipc.on('duration', (event, duration) => {
        result.innerHTML = `Video is ${duration} seconds!`    
    })
    ipc.send('video:submit', path)

})

3 - On ffprobe process on main.js, I was calling method with wrong params. It's necessary to pass the err param first, then data param, this way:

main.js:

ffmpeg.ffprobe(path, (err, metadata) => {
    let duration = metadata.format.duration
    console.log(duration)
    event.reply('duration', duration)
})

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.