iemong_のアイコン画像
iemong_ 2021年05月16日作成
製作品 製作品 閲覧数 2569
iemong_ 2021年05月16日作成 製作品 製作品 閲覧数 2569

Obnizでエアロバイクの回転数を取得して、YouTubeの再生速度を変更する

Obnizでエアロバイクの回転数を取得して、YouTubeの再生速度を変更する

概要

在宅で働く時間が増え、一日の歩数が1/5くらいまで減っていました。そこで、運動不足を解消するために、エアロバイクを購入し、NetflixやYouTubeの動画コンテンツを見ながら運動するようにしました。ですが、動画コンテンツの方に夢中になって、ペダルをこぐ足が止まっていることがよくありました。そこで、エアロバイクの回転数を取得して、それをYoutubeの再生速度に反映される装置が今回作ったものになります。

DEMO

ここに動画が表示されます

部品

部品 購入リンク
obniz Board https://obniz.com/ja/products/obnizboard
Seeed Studio Grove-Magnetic Switch https://jp.rs-online.com/web/p/sensor-development-tools/1793718/
Grove 4ピンコネクタ - ジャンパーピン変換ケーブル https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4K34
エアロバイク (ペダルが鉄製のモノであれば何でもOK) https://www.amazon.co.jp/dp/B089CTFHPP
磁石 https://www.amazon.co.jp/dp/B07WY57ZBP

設計図

キャプションを入力できます

ペダルについた磁石がMagnetic Switchと交差する度にカウントアップする。3秒毎にペダルの回転数を計算して、動画の再生スピードを変更しています。

配線図 & 組み立て

キャプションを入力できます

キャプションを入力できます

キャプションを入力できます

キャプションを入力できます

ソースコード

<script lang="ts">
  // obniz
  const obniz_id = "8844-1752";
  const obniz = new window.Obniz(obniz_id);
  let revolutionNum = 0;
  let isHit = false;
  let timerId: number | null = null;
  let diff = 0;
  let prevSpeed = 0;
  const intervalSecond = 3;

  // youtube
  let player: YT.Player | null = null;
  let youtubeId = "";
  let playbackRate = 0;

  //during obniz connection
  obniz.onconnect = async () => {
    obniz.io4?.drive("5v");
    obniz.io4?.output(true);
    obniz.io2?.output(false);
    obniz.io1?.output(false);
    obniz.ad0?.start((num) => {
      if (num > 4) {
        if (isHit) return;
        isHit = true;
        revolutionNum += 1;
      } else {
        if (!isHit) return;
        if (timerId) {
          console.log("cancel");
          clearTimeout(timerId);
          timerId = null;
        }
        timerId = window.setTimeout(() => {
          isHit = false;
        });
      }
    });
  };

  setInterval(() => {
    const currentDiff = revolutionNum / intervalSecond;
    speed = (currentDiff + prevSpeed) / 2;

    console.log(revolutionNum, speed);

    if (speed > 1.2) {
      playbackRate = 2;
    } else if (speed > 0.9) {
      playbackRate = 1.5;
    } else if (speed > 0.6) {
      playbackRate = 1.0;
    } else if (speed > 0.3) {
      playbackRate = 0.5;
    } else {
      playbackRate = 0;
    }

    if (playbackRate) {
      // 再生スピードを設定する
      player?.setPlaybackRate(playbackRate);
      // 再生中じゃなかったら、再生する
      if (player?.getPlayerState() !== 1) {
        player?.playVideo();
      }
    } else {
      // 再生スピードが0なので、一時停止
      player?.pauseVideo();
    }

    prevSpeed = speed;
    revolutionNum = 0;
  }, intervalSecond * 1000);

  // YouTubeのセットアップ
  window.onYouTubeIframeAPIReady = () => {
    player = new YT.Player("player", {
      playerVars: {
        loop: 1,
        controls: 1,
        autoplay: 0,
        showinfo: 0,
        rel: 0,
      },
      events: {
        onReady: (event) => {
          console.log("ready…");
          console.log(event);
        },
        onStateChange: (event) => {
          console.log(event);
        },
      },
    });
  };

  const loadVideo = () => {
    (player as YT.Player)?.cueVideoById(youtubeId);
  };
</script>

<main class="main">
  <div class="youtube-wrapper">
    <div id="player" class="youtube-player"></div>
  </div>
  <div class="speed">
    <p class="playback-title">再生速度</p>
    <p>{playbackRate}</p>
    <p class="speed-title">SPEED</p>
    <p>{speed}</p>
  </div>
  <div class="text-box">
    <label class="input-label">
      <span>Enter YouTube ID : </span>
      <input class="input" type="url" bind:value="{youtubeId}" />
    </label>
  </div>
  {#if youtubeId}
    <button on:click="{loadVideo}">動画を読み込む</button>
  {/if}
</main>

<style lang="scss">
  .main {
    --bg-color: #181818;
    --text-color: #aaa;
    --bd-color: #303030;

    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow: hidden;
    background-color: var(--bg-color);

    .youtube-wrapper {
      position: relative;
      width: 100%;
      max-width: 980px;
      aspect-ratio: 16 / 9;
      text-align: center;
      overflow: hidden;
    }

    .youtube-player {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }

    .text-box {
      margin: 16px auto 0;
      text-align: center;
    }

    .input-label {
      display: inline-block;
      color: var(--text-color);
    }

    .input {
      color: var(--text-color);
      border: 1px solid var(--bd-color);
      background-color: #121212;
    }

    .speed {
      position: absolute;
      right: 20px;
      top: 20px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      width: 200px;
      text-align: center;
      color: var(--text-color);
      font-size: 24px;
      font-weight: bold;
    }

    .playback-title {
      margin-bottom: 0.5em;
      font-size: 24px;
      font-weight: bold;
    }

    .speed-title {
      margin: 0.5em 0;
      font-size: 24px;
      font-weight: bold;
    }
  }
</style>

レポジトリはこちら

obike-app/ 以下で yarn or npm install コマンドを実行後、yarn dev or npm run dev でローカルサーバーで起動できます。

まとめ

これで、YouTubeを見ながら、エアロバイクを漕ぎ続けれることができるようになりました。
車窓の風景を流してる動画などを再生素材として、使うと自転車で進んでる感があって違った楽しみ方も発見できました。

2
  • iemong_ さんが 2021/05/16 に 編集 をしました。 (メッセージ: 初版)
ログインしてコメントを投稿する