본문 바로가기

목차 🡻


프로젝트/NodeJs-유튜브 음질 뷰어

노드에서 유튜브 영상 포맷 정보 가져오기

by ​​​​ 2020. 10. 5.

어제 포맷정보의 비트레이트만으로 음질을 구별할수있단걸 알았습니다.

오늘은 파이썬으로 제작된 youtube-dl -F 를 노드에서 구현해야합니다

1. youtube-dl의 바이너리 파일을 노드에서 실행하는방법

2. youtube-dl의 원본인 파이썬 코드를 보고 노드로 재해석해 같은 리퀘스트를 보내는방법

이렇게 대충 2가지방법이 생각나는데 바이너리를 실행해도 3초는 안넘을거같아서  바이너리를 실행할겁니다

그리고 바이너리를 실행할땐 execa 모듈을 사용해 async await문법을 사용하려고합니다

아래 코드가 바이너리를 실행해 포맷 리스트를 가져오는 코드입니다.

const execa=require('execa')
const getFormatList = (url) =>
  new Promise(async (resolve, reject) => {
    const { stdout } = await execa("youtube-dl.exe", ["-F", url]);
    const temp = stdout.split("\n");
    resolve(
      temp.slice(
        temp.indexOf("format code  extension  resolution note") + 1,
        temp.length
      )
    );
  });

바이너리를 그대로 실행하고, 포맷이 시작되는부분을 가져오는 코드라서 간단합니다

결과
(23) ['249          webm       audio only tiny   52k , opus @ 50k (48000Hz), 1.44MiB', '250          webm       audio only tiny   70k , opus @ 70k (48000Hz), 1.91MiB', '140          m4a        audio only tiny  130k , m…ash container, mp4a.40.2@128k (44100Hz), 3.79MiB', '251          webm       audio only tiny  139k , opus @160k (48000Hz), 3.78MiB', '394          mp4        256x144    144p   90k , av01.0.00M.08, 20fps, video only, 1.79MiB', '278          webm       256x144    144p  102k , webm container, vp9, 20fps, video only, 2.15MiB', '160          mp4        256x144    144p  110k , avc1.4d400b, 20fps, video only, 1.67MiB', '395          mp4        426x240    240p  230k , av01.0.00M.08, 20fps, video only, 3.36MiB', '242          webm       426x240    240p  243k , vp9, 20fps, video only, 4.63MiB', '133          mp4        426x240    240p  244k , avc1.4d4015, 20fps, video only, 3.20MiB', '396          mp4        640x360    360p  435k , av01.0.01M.08, 20fps, video only, 6.60MiB', '243          webm       640x360    360p  445k , vp9, 20fps, video only, 8.53MiB', '134          mp4        640x360    360p  618k , avc1.4d4016, 20fps, video only, 7.36MiB', '397          mp4        854x480    480p  739k , av01.0.04M.08, 20fps, video only, 11.39MiB', '244          webm       854x480    480p  813k , vp9, 20fps, video only, 14.93MiB', '135          mp4        854x480    480p 1099k , avc1.4d401e, 20fps, video only, 13.59MiB', '398          mp4        1280x720   720p 1279k , av01.0.05M.08, 20fps, video only, 21.01MiB', '247          webm       1280x720   720p 1622k , vp9, 20fps, video only, 28.80MiB', '136          mp4        1280x720   720p 1766k , avc1.4d401f, 20fps, video only, 24.31MiB', '399          mp4        1920x1080  1080p 1791k , av01.0.08M.08, 20fps, video only, 36.83MiB', '248          webm       1920x1080  1080p 2766k , vp9, 20fps, video only, 51.14MiB', '137          mp4        1920x1080  1080p 2782k , avc1.640028, 20fps, video only, 43.01MiB', '18           mp4        640x360    360p  456k , a…20fps, mp4a.40.2@ 96k (44100Hz), 13.36MiB (best)']

 

이제 이 포맷정보들에서 마지막(최고음질)인 audio only tiny 포맷을 찾아서 비트레이트값을 얻어오기만 하면됩니다.

const getAudioBitrate = async (url) => {
  const formatList = await getFormatList(url);
  let bestAudioOnlyFormat;
  for (let i = 0; i < formatList.length; i++) {
    const format = formatList[i];
    if (!format.includes("audio")) {
      bestAudioOnlyFormat = formatList[i - 1];
      console.log("bestAudioOnlyFormat: " + bestAudioOnlyFormat);
      break;
    }
  }
  const kIndex = bestAudioOnlyFormat.indexOf("k");
  for (let i = kIndex - 1; ; i--) {
    if (bestAudioOnlyFormat[i] == " ") {
      const bestAudioBitrate = bestAudioOnlyFormat.slice(i + 1, kIndex);
      console.log("bestAudioBitrate: " + bestAudioBitrate);
      return bestAudioBitrate;
    }
  }
};

첫번째 반복으로 마지막 audio only포맷을 찾고 두번째 반복으로 그 포맷의 비트레이트를 가져옵니다.

결과
bestAudioOnlyFormat: 251          webm       audio only tiny  139k , opus @160k (48000Hz), 3.78MiB
bestAudioBitrate: 139

비트레이트가 139로 잘 나오는걸 확인할수있죠

오늘은 비트레이트를 얻어오는 함수를 완성했습니다.

간단하게 youtube-dl 바이너리를 실행해서 파싱하는데만 집중하면 됐지만,

나중에 바이너리로 인한 문제점이 생긴다면 직접 유튜브 api를 사용할수도 있겠네요