Tempo Di Valse

[Electron] Video 사이즈 정보를 가져오기 본문

개발/Electron

[Electron] Video 사이즈 정보를 가져오기

TempoDiValse 2022. 5. 18. 13:11

Renderer 프로세스 였다면 DOM Element 를 이용하여 쉽게 Video 를 가져올 수 있겠지만, Main 프로세스 에서는 Node.js 에서 돌아가는 환경이기 때문에 DOM 에 대한 모듈이 있지 않기 때문에 이를 활용하기 위해서 사이즈를 알기위한 또 다른 모듈을 찾아 설치해야 한다.

 

이미지의 경우에는 npm 에서 여러 모듈들을 찾을 수 있었다. 그러나 비디오의 경우에는 사이즈 정보만 가져오는데에도 너무나 불필요하고 많은 모듈들을 설치해야 한다는 것에, "굳이 왜 쓰지도 않는 걸 다 깔아야 하지?" 라는 생각이 있어서 어떻게 할까 하다가 결국 알아낸 방법이다.


지금까지 일반적인 스크립트로 비디오의 사이즈를 구하는 방법을 다음 처럼 알아내곤 했었다.

function getVideoSize(){
    const video = document.createElement('video')

    const P = new Promise((resolve, reject) => {
        video.addEventListener('loadedmetadata', function(){
            resolve({
                width: this.videoWidth,
                height: this.videoHeight
            })
        })
    
        video.addEventListener('error', function(err){
            reject(err)
        })
    })

    video.src = src

    return P
}

그러나 Electron 의 구조상 Renderer 프로세스가 아닌 Main 프로세스에서는 DOM 자체를 만들거나 접근하거나 할 수 없다. 그렇다고 ContextBridge 를 통해 API 를 하나 파는 것도 좀 아닌 것 같았다. 그러다가 Renderer 프로세스에 접근할 수 있는 방법을 하나 알아냈으니.. 그것은 바로 WebContents API 를 이용한 executeJavascript 를 이용하는 것이다. WebContents 는 Main 에서도 직접적으로 Renderer 프로세스의 Javascript 에 접근 할 수 있기 때문에 스크립트를 사용하여 사이즈를 얻어야 하는 위의 방법으로 알맞는 방식이었다.

 

WebContents API 는 BrowserWindow 객체안에 있기 떄문에 따로 설정을 하지 않아도 다음의 방법으로 얻어올 수 있다.

const window = BrowserWindow.getFocusedWindow()

window.webContents.[....]

현재 띄워져있는 윈도우의 정보를 가져와 webContents 프로퍼티에 접근하여 WebContents 의 API 를 사용할 수 있게 된다. 메소드에 executeJavascript 를 사용하게 되면 UI 부분에 정의된 메소드들을 실행 할 수 있는데, 생각해보니 굳이 따로 밖에 정의를 해서 메소드를 열어 둘 필요가 있을까 생각이 되었다. 그러다가 생각한 방법이 기존에 사용했던 메소드를 IIFE 식으로 호출하도록 변경하는 것을 생각해냈다.

 

IIFE 는 음... 구글 찾아보면 많이 나오는 방법이라 설명은 생략하도록 한다. 그래서 변경을 해보도록 한다.

((src) => {
    const video = document.createElement('video')

    const P = new Promise((resolve, reject) => {
        video.addEventListener('loadedmetadata', function(){
            resolve({
                width: this.videoWidth,
                height: this.videoHeight
            })
        })
    
        video.addEventListener('error', function(err){
            reject(err)
        })
    })

    video.src = src

    return P
})(path)

 

 

원래 사용하던 방식에서 IIFE로 변경을 하였고, path 자리에다가 비디오의 경로를 넣어주면 src 로 넘어가지는 방식이다. 리턴 값은 Promise 객체를 전달하기 때문에 비디오가 로드되고 정보를 얻어오고 나면 then 으로 데이터를 받거나 async/await 패턴을 사용 할 수 있다.

 

사용 방법은 이 소스 자체가 메소드를 정의하고 실행하여 값을 받아오는 것이기 때문에 Renderer 프로세스 내에 정의를 하지 않아도 executeJavascript 를 통해 실행할 수 있다. 그래서,

const path = "VIDEO_LOCAL_PATH"

const code = `
    ((src) => {
        const video = document.createElement('video')
    
        const P = new Promise((resolve, reject) => {
            video.addEventListener('loadedmetadata', function(){
                resolve({
                    width: this.videoWidth,
                    height: this.videoHeight
                })
            })
        
            video.addEventListener('error', function(err){
                reject(err)
            })
        })
    
        video.src = src
    
        return P
    })('${path}')
`

const window = BrowserWindow.getFocusedWindow()

const size = await window.webContents.executeJavascript(code)

이런 식으로 사용할 수 있다. 예시에서는 await 를 사용하였기 때문에 해당 기능이 들어간 메소드는 async 가 달려 있어야 될 것이다.

반응형
Comments