• Home
  • A W E T I O N . で YouTube の埋め込みに対応した

A W E T I O N . で YouTube の埋め込みに対応した

thumbnail

A W E T I O N . で YouTube の埋め込みに対応しました。

YouTubeを埋め込んだ場合のレスポンス

YouTube の埋め込みで何が返ってくるかを確認してみます。

utils\notion.tsxrenderBlocks

  • console.log(value);
  • console.log(type);
  • を確認します。

    utils\notion.tsx

    const renderBlock = (block: BlockObjectResponse) => {
      const { type, id } = block;
      const value = block[type];
    
    	console.log(type); // eslint-disable-line no-console
      console.log(value); // eslint-disable-line no-console

    typeには videoが返ってきました。

    //console.log(type);
    video
    
    //console.log(value);
    {
      caption: [],
      type: 'external',
      external: { url: 'https://www.youtube.com/watch?v=8ptQj7dgwIo' }
    }

    switch の分岐に case "video”: を追加して、YouTube を埋め込んだ場合の対応を実装します。

    case "video”: 内で、console.log(value.external.url); を確認すると、埋め込んだ YouTube の URL が返ってきます。

    utils\notion.tsx

    case "video": {
          console.log(value.external.url); // eslint-disable-line no-console

    YouTube の ID を URL から抜き出す

    YouTube の ID は URL の v=****** の ***** の部分です。

    下記の URL の場合は、8ptQj7dgwIo がIDとなります。

    https://www.youtube.com/watch?v=8ptQj7dgwIo

    以下の PR を参考にさせていただきます。

  • Support youtube video blocks by otoyo · Pull Request #94 · otoyo/easy-notion-blog · GitHub
  • まずは、 utils\notion.tsx 内に以下を追記します。

    case "video": {
          let youtubeurl: URL;
          try {
            youtubeurl = new URL(value.external.url);
          } catch {
            return null;
          }

    URL オブジェクトを利用すると便利です。

    utils\youtube.ts を作成して、以下を実装します。

    utils\youtube.ts

    export const isYouTubeURL = (url: URL): boolean => {
      if (["www.youtube.com", "youtu.be"].includes(url.hostname)) {
        return true;
      }
      return false;
    };
    
    // Supported URL
    //
    // - http://youtu.be/0zM3nApSvMg
    // - http://www.youtube.com/watch?v=0zM3nApSvMg&feature=feedrec_grec_index
    // - http://www.youtube.com/watch?v=0zM3nApSvMg#t=0m10s
    // - http://www.youtube.com/watch?v=0zM3nApSvMg
    // - http://www.youtube.com/v/0zM3nApSvMg?fs=1&hl=en_US&rel=0
    // - http://www.youtube.com/embed/0zM3nApSvMg?rel=0
    export const parseYouTubeVideoId = (url: URL): string => {
      if (!isYouTubeURL(url)) return "";
    
      if (url.hostname === "youtu.be") {
        return url.pathname.split("/")[1];
      }
      if (url.pathname === "/watch") {
        return url.searchParams.get("v");
      }
      const elements = url.pathname.split("/");
    
      if (elements.length < 2) return "";
    
      if (elements[1] === "v" || elements[1] === "embed") {
        return elements[2];
      }
    
      return "";
    };

    これで YouTube の ID を抜き出す関数の準備はできたので、utils\notion.tsx で ID を受け取ります。

    const videoId = parseYouTubeVideoId(youtubeurl);
          if (videoId === "") {
            return null;
          }

    iframe で埋め込む

    初めは react-youtube というライブラリを利用しようとしましたが、なぜか動画が表示されず、うまくいかなかったので iframe で埋め込むことにしました。

    utils\notion.tsx

    import { parseYouTubeVideoId } from "@/utils/youtube";
    
    const renderBlock = (block: BlockObjectResponse) => {
      const { type, id } = block;
      const value = block[type];
    
      switch (type) {
    		・
    		・
    		・
        case "video": {
          let youtubeurl: URL;
          try {
            youtubeurl = new URL(value.external.url);
          } catch {
            return null;
          }
    
          const videoId = parseYouTubeVideoId(youtubeurl);
          if (videoId === "") {
            return null;
          }
    
          return (
            <div className="video">
              <iframe
                src={`https://www.youtube.com/embed/${videoId}`}
                title="YouTube video player"
                frameBorder="0"
                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                allowFullScreen
                key={videoId}
              />
            </div>
          );
        }
      }
    };

    レスポンシブ対応

    YouTube の埋め込みをレスポンシブ対応するために、 components\content.tsx に以下を追加します。

    :global(.video) {
      position: relative;
      width: 100%;
      height: 0;
      padding-top: 56.25%;
      margin-top: 2rem;
      margin-bottom: 2rem;
    }
    :global(.video iframe) {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }

    これで完成です。

    終わりに

    今回は YouTube の動画の埋め込みを実装しましたが、ツイッターの埋め込みなど対応できていないブロックもあるので、随時対応していく予定です。

    avatar

    PROFILE

    チャベス

    Product Development Engineer, Notioner

    TAG