- 전체
- 명
- 오늘 찾아주신 분
- 명
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 가 달려 있어야 될 것이다.
[Electron] Build 한 후, net::ERR_FILE_NOT_FOUND 가 나는 경우. (0) | 2022.06.17 |
---|---|
[Electron] electron-builder 의 files 에 대해 알아본다. (0) | 2022.06.17 |
[Electron] <img> 태그에 로컬 이미지 로드하기 (0) | 2022.04.27 |
[Electron] Electron 과 Vue 의 간단한 연결 방법 (0) | 2022.03.28 |