본문 바로가기
개발/개발지식

[유튜브] url로 영상의 정보를 가져오는 기능 만들기

by 핸디(Handy) 2023. 7. 25.

들어가며

이번 글에서는 유튜브 링크를 기반으로 해당 영상의 meta 정보를 가져와 활용하는 예제를 살펴보겠습니다.

최근 업무에서 유튜브 링크로 실제 데이터를 가져오기 전에 브라우저 단에서 10분짜리 영상인지를 판별하는 로직이 필요했습니다.

서버에서 10분 이상인 영상의 경우 처리할 수 없다는 에러코드가 나옵니다.

하지만 모든 업로드 프로세스가 마무리되고 난후에 날아오는 에러코드이기에 UX적으로 불편했습니다.

그래서 이번에는 유튜브 링크로 바로 meta를 가져와 유저에게 알려주는 기능을 개발하게 되었습니다.

유튜브 링크로 바로 meta를 가져와 유저에게 알려주는 기능

본문에 들어가기 전에 완성된 기능을 보고 가겠습니다.

시간을 잘 가져오는 기능

기능 구현

일단 해당 기능을 구현하기 전에 라이브러리가 있나 살펴보았습니다.

여러 가지 라이브러리를 살펴보았는데요. 좋은 라이브러리가 없어 보였습니다.

그래서 직접 기능 개발로 가닥을 잡고 구현 계획을 세워봅니다.

일반적으로 이런류의 기능은 공식 api를 사용하는 게 가장 깔끔합니다.

아마도 google에서 youtube 정보를 가져오는 api를 제공할 겁니다.

api를 살펴보기에 앞써 우리의 코딩친구 챗 GPT에게 물어봅니다.

챗 CPT

Q) how to get video duration from youtube url in js??

how to get video duration from youtube url in js

위에서 예상한대로 구글의 api를 사용하라고 나와있네요.

그럼 한번씩 따라가 보겠습니다.

구글 클라우드 콘솔

이제 api 사용을 위한 사전 준비를 하러 가보겠습니다.

 

 

Google 클라우드 플랫폼

로그인 Google 클라우드 플랫폼으로 이동

accounts.google.com

YouTube Data API v3

여기에서 YouTube Data API v3를 검색해서 들어와 줍니다.

YouTube Data API v3

사용을 클릭한후 이제 api_key를 발급하러 가보겠습니다

api_key 발급

API 및 서비스 > 사용자 인증 정보탭으로 들어가면 됩니다.

그다음에 키에 대한 추가 사항을 주겠습니다. 

여기에선 애플리케이션 제한은 그대로 두고, API만 YouTube Data API v3 만 허용하도록 하겠습니다.

경고

만약에 앞에서 YouTube Data API v3 사용하기를 하지 않으셨다면 API select 창에서 YouTube Data API v3가 안 뜹니다.

코드 구현

일단 전체 코드부터 뿌리고 함수단위로 다시 살펴보겠습니다.

(참고 | 현재 프로젝트는 Next, Typescript를 사용하고 있습니다.)

타입정보는 제가 ㅇ

import axios from "axios";

const apiKey = process.env.NEXT_PUBLIC_YOUTUBE_DATA_V3_KEY;

interface YoutubeVideoMetaResponse {
  kind: string;
  etag: string;
  items: [
    {
      kind: string;
      etag: string;
      id: string;
      contentDetails: {
        duration: string;
        dimension: string;
        definition: string;
        caption: string;
        licensedContent: boolean;
        contentRating: {};
        projection: string;
      };
    }
  ];
  pageInfo: {
    totalResults: number;
    resultsPerPage: number;
  };
}

export async function getDurationByUrl(url: string) {
  const videoId = extractVideoId(url);

  try {
    const response = await axios.get<YoutubeVideoMetaResponse>(
      `https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=${videoId}&key=${apiKey}`
    );

    if (response.data) {
      const durationISO8601 = response.data.items[0].contentDetails.duration;
      const duration = parseISO8601DurationToSeconds(durationISO8601);
      return {
        seconds: duration,
        minutes: Math.floor(duration / 60),
      };
    }
  } catch (e) {
    console.error(e);
  }
  return {
    seconds: 0,
    minutes: 0,
  };
}

function extractVideoId(url: string) {
  //group 3 should give the youtube video id
  /*
	https://www.youtube.com/watch?v=7woVTuN8k3c
    http://youtube.com/watch?v=7woVTuN8k3c
    https://www.youtube.com/embed/7woVTuN8k3c
    https://youtu.be/7woVTuN8k3c
    https://youtu.be/7woVTuN8k3c?t=9s
    https://www.youtube.com/shorts/WzXPNDxuOS8
    https://www.youtube.com/watch?v=7MKEOfSP2s4
    https://youtu.be/7MKEOfSP2s4
    https://www.youtube.com/shorts/WzXPNDxuOS8
   */
  const regex = /(.*?)(^|\/|v=)([a-z0-9_-]{11})(.*)?/gim;
  const match = regex.exec(url);
  return match && match[3];
}
function parseISO8601DurationToSeconds(duration) {
  const regex = /P(?:(\d+)D)?T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/;
  const match = regex.exec(duration);
  const days = parseInt(match[1]) || 0;
  const hours = parseInt(match[2]) || 0;
  const minutes = parseInt(match[3]) || 0;
  const seconds = parseInt(match[4]) || 0;

  return days * 86400 + hours * 3600 + minutes * 60 + seconds;
}

getDurationByUrl(url: string)

가장 먼저 트리거 되는 함수입니다. 

간단하게 유튜브 url를 받습니다.

그리고 저는 seconds, minutes를 반환하도록 구현했습니다.

extractVideoId(url : string)

링크에서 videoId를 뽑아오는 함수입니다.

chatGPT가 뽑아준 Regex는 현재 있는 가능한 모든 경우의 수를 커버하지 못함으로 별도로 구현한 Regex로 변경하였습니다.

parseISO8601 DurationToSeconds(duration: string)

이 함수가 약간 특이해 보일 수 있는데요.

현재 YouTube Data API v3의 response 스펙에서 duration의 경우 ISO8601로 값이 옵니다.

이 값을 number로 된 seconds로 변환해 주는 함수입니다. 

상세 스펙

상세 스펙을 보시고 싶으면 언제나 공식문서를 추천합니다.

 

Videos  |  YouTube Data API  |  Google for Developers

Videos 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. video 리소스는 YouTube 동영상을 나타냅니다. 메소드 API는 videos 리소스에 다음 메소드를 지원합니다. getRat

developers.google.com

 

결과

유튜브를 들어가 가장 먼저 뜬 뉴스의 링크를 가져와서 테스트해 보았는데요.

소수점 반올림이 있지만 시간을 제대로 가져오는 모습을 확인할 수 있었습니다.

추가 기능

기능 구현을 그만둘까 싶다가 아무래도 출력 포맷이 이상한 거 같아 day.js를 추가하여 개선하기로 합니다.

getHHMMSSDurationByUrl  (day.js)

import dayjs from "dayjs";
import duration from "dayjs/plugin/duration";
dayjs.extend(duration);

export async function getHHMMSSDurationByUrl(url: string) {
  const videoId = extractVideoId(url);

  try {
    const response = await axios.get<YoutubeVideoMetaResponse>(
      `https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=${videoId}&key=${apiKey}`
    );

    if (response.data) {
      const durationISO8601 = response.data.items[0].contentDetails.duration;
      const seconds = parseISO8601DurationToSeconds(durationISO8601);
      return dayjs.duration(seconds, "seconds").format("HH:mm:ss");
    }
  } catch (e) {
    console.error(e);
  }
  return "00:00:00";
}

함수명에 포맷정보도 들어가도록 변경하고 리턴값을 수정하겠습니다.

이제 잘 사용하시면 되겠습니다.

duration 말고 다른 정보는?

글을 쓰다보니 meta라고 말하고 저에게 필요한 duration만 가져오는 코드가 되어버렸습니다.

다른 meta를 가져오고 싶으시다면 api 주소를 아래처럼 바꿔주면 됩니다.

// duration용
`https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=${videoId}&key=${apiKey}`

// 전체 meta용
`https://www.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId}&key=${apiKey}`

이렇게 되면 더욱 많은 정보가 날라옵니다.

다만 저는 필요한 정보만 가져오는 api를 추구하기 때문에 좀더 세부적인 정보를 가져올 수 있는 contentDetails 쿼리로 했습니다.

혹시 다른 정보도 필요하시다면 이렇게 사용해보세요.

 

마무리

이번글에서는 유튜브의 url를 이용해서 duration를 가져오는 기능을 만들어보았습니다.

api설정하는 방법부터 그리고 실제 동작하는 코드를 만들어보았는데요.

생각보다 간단한 기능이지만 한번 만들어두면 언젠가 쓰일 것 같은 그런 기능입니다.

끝.

댓글