Nuxt.jsでSpotifyのoEmbed APIをプラグイン化

Spotifyでは、oEmbedの方法で、未ログインでも再生ができるWEB向けのiFrameプレイヤーをAPIから取得できる。これをNuxt.jsのプラグイン化する方法。

通常、iFrameのURLをHTMLに記述してプレイヤーを埋め込むが、そのiFrameの内容をJSON形式でも取得できる。

動作環境

通常のiFrame

<iframe style="border-radius:12px" src="https://open.spotify.com/embed/playlist/25Wlc36nhO0sd8mNOQbOv1?utm_source=generator" width="100%" height="380" frameBorder="0" allowfullscreen="" allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"></iframe>

このようHTMLを埋め込むと、

と、表示される。

取得API

既出のiFrameのソースコードをこのAPIで取得可能

https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Fplaylist%2F{id}

{id}の部分をプレイリストのIDを指定する。

取得結果

{
  html: "<iframe style="border-radius: 12px" width="100%" height="380" title="Spotify Embed: 昼の放送 #27" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" src="https://open.spotify.com/embed/playlist/25Wlc36nhO0sd8mNOQbOv1?utm_source=oembed"></iframe>",
  width: 456,
  height: 380,
  version: "1.0",
  provider_name: "Spotify",
  provider_url: "https://spotify.com",
  type: "rich",
  title: "昼の放送 #27",
  thumbnail_url: "https://mosaic.scdn.co/300/ab67616d0000b273115c265fae60f66103a965c9ab67616d0000b2736dba235db4ccbec24606f0d9ab67616d0000b273bf6bcb4f1d2c4c49e67d6999ab67616d0000b273d6c059712a4916f1b278405a",
  thumbnail_width: 300,
  thumbnail_height: 300
}

実装的には、プレイリストのタイトル、サムネイル画像のURLを取得できる点が便利。

プラグイング化

import { Plugin } from '@nuxt/types'
import { NuxtHTTPInstance } from '@nuxt/http'

class SpotifyEmbed {
  http: NuxtHTTPInstance

  constructor(http: NuxtHTTPInstance) {
    this.http = http
  }

  /**
   * iFrameを取得
   * @param id spotifyのプレイリストのid
   * @returns
   */
  public async get(id: string): Promise<any> {
    try {
      return await this.http.$get(
        `https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Fplaylist%2F${id}`
      )
    } catch (error) {
      console.log('response error', error)
    }
  }
}

export const spotifyEmbedPlugin: Plugin = (context, inject) => {
  const spotifyEmbed = new SpotifyEmbed(context.app.$http)

  inject('spotifyEmbed', spotifyEmbed)
}
export default spotifyEmbedPlugin

declare module '@nuxt/types' {
  interface Context {
    $spotifyEmbed: SpotifyEmbed
  }
}

.vueファイルからはこういう形で使う

<script lang="ts">
...

import { useSpotify } from '@/composables/spotifyState'
import {
  defineComponent,
  ref,
  useContext,
} from '@nuxtjs/composition-api'
...

export default defineComponent({
    const { app } = useContext()
...

const spotifyId = '25Wlc36nhO0sd8mNOQbOv1'

...

  setup(props) {
    ...

    async created() {
      const searchResult = await app.$spotifyEmbed.get(spotifyId)
    }

    ...
  }
}

asyncを宣言しているメソッド内で、await で実行結果を受け取ることができる。後は、ref宣言した変数にhtml部分を入れて、テンプレート内に表示することが可能。

    const spotifyIFrame = ref({ html: '' })
      const searchResult = await app.$spotifyEmbed.get(spotifyId.value)
      spotifyIFrame.value = searchResult

Vuetifyを使ってテンプレートに表示する例

<div v-html="spotifyIFrame.html"></div>

refで初期化する際に、htmlを空白にすることで、レンダリングのエラーを回避している