01
Instalação
Um arquivo só. Baixe para o seu projeto (recomendado: você controla a versão e não depende de outro site) ou carregue direto do metaphi.tech.
Baixe para a pasta pública do projeto (
public/,static/,www/…):Terminalcurl -fsSL https://metaphi.tech/jukebox/v3/metaphi-jukebox.min.js -o metaphi-jukebox.jsCarregue como módulo, uma vez por página, perto do fim do
<body>:HTML<script type="module" src="/metaphi-jukebox.js"></script>Adicione o
<metaphi-jukebox>com as suas músicas (veja Músicas) ou monte o seu no Customize e copie o código.
O endereço /jukebox/v3/ recebe correções sem mudar a API da versão 3. Responde com CORS liberado e cache de um dia.
<script type="module" src="https://metaphi.tech/jukebox/v3/metaphi-jukebox.min.js"></script>O arquivo publicado é minificado e ofuscado, com a licença MIT e os créditos no comentário do topo.
Monte o seu no Customize, abra Copy for AI e escolha Copiar prompt. O prompt leva o comando de instalação, a sua configuração, as regras (CSP, frameworks, vídeos na página) e o link desta documentação em Markdown, para o Claude, o ChatGPT, o Cursor ou o Copilot instalarem no seu projeto.
02
Músicas
Cada música é um disco no leque. Use o id do vídeo ou o link inteiro. Um disco com playlist toca vários vídeos em sequência, e o próprio player passa de um ao outro (no celular, sem precisar de outro toque).
<metaphi-jukebox accent="#2d81ff" position="bottom-left">
<script type="application/json">
{
"tracks": [
{ "id": "https://youtu.be/Wv5kt7d8p1A", "title": "City Ghosts", "subtitle": "NEROX · Gangster Trap" },
{ "id": "7MHgdIu7FlI", "title": "Soft Collision", "subtitle": "Titan Beats · Deep House Mix" },
{
"title": "Playlist da casa",
"subtitle": "Shuffle · 3 faixas",
"playlist": ["Tx9zMFodNtA", "SAd_oy2Sc3Y", "NEMsIHVejWM"],
"cover": { "lg": "/musica/capa.webp", "sm": "/musica/capa-sm.webp" }
}
]
}
</script>
</metaphi-jukebox>| Campo | Tipo | Descrição |
|---|---|---|
id | texto | Id do vídeo (11 caracteres) ou o link inteiro (youtube.com/watch?v=…, youtu.be/…, /shorts/…, /live/…). |
title | texto | Título no leque e no leitor de tela. |
subtitle | texto | Linha de baixo: artista, gênero, duração. |
playlist | texto[] | Disco-playlist: vários vídeos, tocados em sequência pelo próprio player (sem precisar de outro toque no celular), com capa empilhada e selo "Playlist · N". |
cover | texto | { lg, sm } | Capa própria. Sem ela, a miniatura do YouTube (i.ytimg.com); na mídia própria, uma capa desenhada com o título. |
src | texto | Mídia própria: o endereço de um arquivo de áudio (mp3, m4a, ogg…) no seu servidor, no lugar do vídeo do YouTube. Toca por <audio>, sem bloqueios do YouTube, e pode tocar em segundo plano (background). |
Músicas sem direitos autorais já usadas
Mixes da FreeWave Music, marcados pelo canal como "No Copyright" e já usados pelo autor em outro sistema. Confira sempre a licença na descrição do vídeo antes de usar.
Morning Chill House #12FreeWave Music · No Copyrightyoutu.be/_3cu8xOA-Tk
Morning Chill House #4FreeWave Music · No Copyrightyoutu.be/fUHjIZNKTaY
Morning Chill House #14FreeWave Music · No Copyrightyoutu.be/cCvrx1N5R2g
Morning Chill House #8FreeWave Music · No Copyrightyoutu.be/wy9mFK5a6JA
Morning Chill House #13FreeWave Music · No Copyrightyoutu.be/tbLHqmwFfm0
Sunset Drive #9FreeWave Music · No Copyrightyoutu.be/-jYPxknmhmI
Sunny Road Trip #5FreeWave Music · No Copyrightyoutu.be/gCHg8E9CFMg
Playlist com músicas curtas
Músicas comuns, de 3 a 5 minutos, acabam rápido e pediriam um toque a cada troca. O disco-playlist resolve: um disco só, com a pilha de capas e o selo "Playlist · N", que toca vários vídeos em sequência. A lista vai inteira para o player do YouTube, que passa de uma faixa à outra sozinho (no celular, sem precisar de outro toque) e recomeça no fim. É o que a METAPHI Playlist desta página faz, com 11 faixas.
Crie um disco com
playlist: a lista dos vídeos, por id ou link (youtu.be, watch?v=, /shorts). Dê umtitle, umsubtitlee, de preferência, umacoverprópria (sem ela, vale a miniatura do primeiro vídeo).A ordem é sorteada a cada vez que o disco começa (
shuffle, ligado por padrão). Para tocar na ordem da lista, useshuffle="false".Vídeo indisponível dentro da lista é pulado. Para esconder os discos-playlist sem tirá-los do código, use
show-playlists="false"(o Customize desta página tem as duas chaves no grupo Playlist).
<metaphi-jukebox shuffle>
<script type="application/json">
{
"tracks": [
{ "id": "Wv5kt7d8p1A", "title": "City Ghosts", "subtitle": "NEROX · Gangster Trap" },
{
"title": "Playlist da casa",
"subtitle": "Shuffle · 4 faixas",
"cover": { "lg": "/musica/playlist.webp", "sm": "/musica/playlist-sm.webp" },
"playlist": [
"https://youtu.be/SAd_oy2Sc3Y",
"https://www.youtube.com/watch?v=NEMsIHVejWM",
"6QBy_Oa5ZmM",
"YrLk4vdY28Q"
]
}
]
}
</script>
</metaphi-jukebox>Links de playlist do YouTube (list=…) não servem: liste os vídeos um a um. Dá para ter mais de um disco-playlist no leque. Com "continuar de onde parou", a playlist volta no mesmo disco, com a ordem sorteada de novo.
Mídia própria (arquivos de áudio)
No lugar do vídeo, use src com o endereço de um arquivo de áudio no seu servidor (mp3, m4a, ogg). O disco toca por<audio>: sem bloqueios do YouTube e com os controles do sistema na tela de bloqueio (Media Session). Com a opçãobackground, a música continua com a página em segundo plano ou a tela bloqueada. Discos do YouTube e de mídia própria podem ficar juntos no mesmo leque.
<metaphi-jukebox background>
<script type="application/json">
{
"tracks": [
{ "src": "/musica/abertura.mp3", "title": "Abertura", "subtitle": "Trilha da casa", "cover": "/musica/abertura.webp" },
{ "src": "/musica/foco.m4a", "title": "Foco", "subtitle": "Trilha da casa" },
{ "id": "_3cu8xOA-Tk", "title": "Morning Chill House #12", "subtitle": "FreeWave Music · No Copyright" }
]
}
</script>
</metaphi-jukebox>| YouTube | Mídia própria | |
|---|---|---|
| Bloqueio pelo YouTube ou pelo dono | Pode acontecer | Não |
| Segundo plano (outra aba, tela bloqueada) | Não no celular: o navegador pausa o player | Sim, com background |
| Controles na tela de bloqueio | Não | Sim (Media Session) |
| Banda e hospedagem | Do YouTube | Do seu servidor |
| Capa | Miniatura do vídeo | cover ou uma capa desenhada com o título |
O servidor precisa responder pedidos com Range (status 206), como fazem os servidores de arquivos estáticos e as CDNs: o Safari exige isso para tocar áudio. No iPhone, o volume é o do aparelho (o Safari ignora o volume definido pela página).
03
Parâmetros
No HTML, como atributos em kebab-case (cover-size="64", allow-custom). Por JavaScript, em camelCase (coverSize: 64). Mude qualquer um depois com jukebox.update({ … }) ou trocando o atributo.
Aparência
Cores, tamanho e lugar do disco na tela. Tudo muda ao vivo, sem recriar o componente.
| Atributo | Opção JS | Tipo | Padrão | Descrição |
|---|---|---|---|---|
accent | accent | cor CSS | #2d81ff | Cor de destaque: botão de tocar, régua, volume, progresso e o selo das músicas enviadas. |
surface | surface | cor CSS | #121316 | Fundo do painel e do botão de liga/desliga. |
ink | ink | cor CSS | #f2f1ee | Cor do texto e das linhas (as transparências saem dela). |
radius | radius | número (px) | 0 | Arredondamento dos cantos. 0 deixa os cantos retos, como no METAPHI. |
position | position | texto | bottom-left | Canto da tela: bottom-left, bottom-right, top-left ou top-right. |
mobile-position | mobilePosition | texto | bottom-right | Canto em telas estreitas (até breakpoint). No celular, o canto direito fica mais perto do polegar. |
cover-size | coverSize | número (px) | 56 | Tamanho da capa no canto. Em telas estreitas ela usa 79% disso. |
offset-x | offsetX | número (px) | 14 | Distância da borda lateral. |
offset-y | offsetY | número (px) | 20 | Distância da borda de baixo (ou de cima). |
blur | blur | número (px) | 10 | Desfoque do vidro do painel. |
backdrop | backdrop | booleano | true | Escurece e desfoca a página atrás do painel aberto. |
breakpoint | breakpoint | número (px) | 760 | Largura do componente abaixo da qual o painel vira uma folha na base da tela. |
z-index | zIndex | número | 41 | Camada do componente na página. |
contained | contained | booleano | false | Fica dentro do elemento target (que precisa de position: relative) em vez de fixo na tela (para demonstrações dentro de um bloco da página). |
Disco e leque
O vinil no canto e o leque de capas em 3D do painel: giro, inclinação, profundidade e navegação.
| Atributo | Opção JS | Tipo | Padrão | Descrição |
|---|---|---|---|---|
rpm | rpm | número | 33 | Rotações por minuto do vinil enquanto toca (33, 45, 78…). Vale para o disco do canto e os do leque. |
peek | peek | booleano | true | O vinil espia para fora da capa com o mouse em cima. |
visible | visible | número | 3 | Capas visíveis de cada lado da capa em foco (1 a 5). |
fan | fan | número (°) | 6 | Inclinação de cada capa vizinha. |
turn | turn | número (°) | 22 | Quanto as vizinhas giram para longe. |
depth | depth | número | 0.5 | Quanto as vizinhas recuam e diminuem. |
spread | spread | número | 0.58 | Distância até as primeiras vizinhas, em fração da capa. |
stack | stack | número | 0.5 | Quanto as capas distantes se empilham: 0 dá espaçamento igual, 1 fica no estilo coverflow. |
dim | dim | número | 0.45 | Quanto as capas distantes apagam. |
auto-rotate | autoRotate | booleano | true | O leque avança sozinho enquanto nada toca. |
interval | interval | número (s) | 4 | Intervalo do avanço automático, em segundos. |
pause-on-hover | pauseOnHover | booleano | true | Pausa o avanço com o cursor em cima do painel. |
loop | loop | booleano | true | A lista dá a volta nas pontas. |
draggable | draggable | booleano | true | Arrastar passa as capas, com inércia e encaixe. |
wheel | wheel | booleano | true | A roda do mouse (ou o trackpad) passa as capas. |
Playlist
Um disco que toca várias músicas curtas do YouTube em sequência, como a "METAPHI Playlist" (11 faixas). O próprio player passa de uma faixa à outra, sem precisar de outro toque no celular. Recomendado para site institucional.
| Atributo | Opção JS | Tipo | Padrão | Descrição |
|---|---|---|---|---|
show-playlists | showPlaylists | booleano | true | Mostra os discos-playlist no leque. Desligado, o leque fica só com os discos de um vídeo. Para montar a sua playlist com músicas comuns, veja "Playlist com músicas curtas". |
shuffle | shuffle | booleano | true | As faixas da playlist tocam em ordem aleatória (sorteada de novo a cada vez que o disco começa). Desligado, tocam na ordem da lista. |
Reprodução
Volume, ordem das músicas, o domínio do player do YouTube e quando ele carrega.
| Atributo | Opção JS | Tipo | Padrão | Descrição |
|---|---|---|---|---|
volume | volume | número (1–100) | 60 | Volume ao ligar a música. |
autoplay | autoplay | booleano | false | Toca no primeiro clique, toque ou tecla em qualquer lugar da página: o gesto que os navegadores exigem para liberar som. O player carrega logo depois da página. Se a pessoa desligar a música, ela não volta sozinha. |
show-progress | showProgress | booleano | false | Mostra a linha do tempo da música no painel (posição, duração e arrastar para avançar). Útil para mixes longos em sistemas; em site institucional, fica de fora. |
start | start | texto | random | Disco inicial: random (sorteado a cada visita), first, a posição (0, 1…) ou o id do vídeo. |
advance | advance | texto | next | Ao terminar uma música: next (o próximo disco), random (outro, sorteado) ou repeat (a mesma de novo). |
background | background | booleano | false | Mídia própria (discos com src) continua tocando com a página em segundo plano ou a tela bloqueada, com os controles do sistema. Músicas do YouTube não têm essa opção: no celular, o navegador pausa o player quando a página sai da tela. |
skip-errors | skipErrors | booleano | true | Vídeo indisponível pula para o próximo disco (até 3 seguidos; depois, aparece o link "Ouvir no YouTube"). |
host | host | texto | auto | auto: youtube.com no computador (vale o login do YouTube do navegador e evita a checagem anti-robô) e youtube-nocookie.com no celular. Ou force youtube ou nocookie. |
prepare | prepare | texto | auto | Quando o player do YouTube carrega. auto: na primeira interação com a página (computador) ou logo depois do carregamento (celular, para o primeiro toque já tocar). Também: interaction, load, hover (ao chegar perto do disco) e manual. |
lang | lang | texto | auto | Idioma dos textos: pt-BR, en ou es. auto segue o lang da página. |
Recursos para sistemasSistemas
Músicas da própria pessoa e continuar de onde parou. Desligados por padrão: recomendados só em sistemas.
| Atributo | Opção JS | Tipo | Padrão | Descrição |
|---|---|---|---|---|
allow-custom | allowCustom | booleano | false | Mostra "Adicionar música": a pessoa cola um link do YouTube, o componente confere a duração no próprio player e o vídeo vira um disco. |
show-examples | showExamples | booleano | true | Mostra o botão "Exemplos" na janela de envio, com links prontos para testar (veja "Exemplos para testar"). Troque a lista com a opção examples ou desligue onde não fizer sentido. |
min-duration | minDuration | número (min) | 25 | Duração mínima da música enviada, em minutos (0 aceita qualquer duração). O padrão pede mixes e sets com mais de 25 minutos. |
max-duration | maxDuration | número (min) | 720 | Duração máxima aceita, em minutos (padrão: 12 horas). |
max-custom | maxCustom | número | 8 | Quantas músicas enviadas ficam guardadas. Ao enviar mais uma, a mais antiga sai. |
storage | storage | texto | local | local: as músicas enviadas ficam no navegador da pessoa (localStorage). none: o seu sistema guarda (no servidor, pela conta da pessoa) com onTrackAdd/onTrackRemove e devolve em customTracks. |
resume | resume | booleano | false | Continuar de onde parou: guarda o disco, a posição e se a música estava ligada. Ao recarregar, o mesmo disco continua do mesmo ponto no primeiro toque, clique ou tecla. |
save-interval | saveInterval | número (s) | 4 | A cada quantos segundos a posição é guardada enquanto toca (também ao sair da página). |
storage-key | storageKey | texto | metaphi-jukebox | Prefixo das chaves no localStorage: <chave>:tracks e <chave>:point. Use um por sistema (ou por usuário). |
Só por JavaScript
Funções e listas não cabem em atributos: passe em createJukebox({ … }) ou jukebox.configure({ … }).
| Opção | Tipo | Descrição |
|---|---|---|
tracks | Track[] | As músicas, na ordem do leque (veja "Músicas"). No HTML, vão num <script type="application/json"> dentro do elemento. |
examples | (link | { id, title, subtitle })[] | Exemplos do botão "Exemplos" da janela de envio. Sem ela, os três exemplos padrão. |
customTracks | Track[] | Músicas enviadas que o seu servidor devolve (com storage: "none"). Entram no fim do leque. |
labels | objeto | Troca qualquer texto, ex.: { title: "Rádio", add: "Enviar mix" }. |
target | Element | seletor | Onde criar o elemento (só em createJukebox). Padrão: document.body. |
onReady | (jukebox) => void | O player do YouTube ficou pronto (ou desistiu: sem rede, bloqueado). |
onStatus | (status, jukebox) => void | playing, paused, waiting (o navegador pediu um toque) ou error. |
onTrackChange | (detail, jukebox) => void | Trocou de disco. detail: { index, track, playing, status, volume }. |
onTrackAdd | (track) => Promise<Track | void> | Antes de guardar uma música enviada: salve no servidor e devolva os dados (ou lance um erro com a mensagem para a pessoa). |
onTrackRemove | (id | null) => Promise<void> | Antes de remover uma música enviada (null: todas). |
04
Recursos para sistemas
Dois recursos para quem volta sempre: a pessoa traz a própria música (mixes e sets com mais de 25 minutos) e a música continua de onde parou depois de recarregar a página. Os dois começam desligados.
allow-custom
Músicas próprias
- No painel, Adicionar música abre o campo do link (youtube.com, youtu.be, /shorts, /live).
- O componente abre o vídeo num player escondido, sem tocar, e lê a duração, o título e o canal. Não precisa de chave de API.
- Aceita só acima da duração mínima (
min-duration, padrão mais de 25 minutos) e até 12 horas. Vídeo curto ou sem permissão de incorporar recebe uma mensagem clara, antes de salvar. - Vira um disco no fim do leque, com o selo Sua música, e já toca. Ficam as 8 últimas (
max-custom): ao enviar mais uma, a mais antiga sai. - O disco enviado tem Remover (confirmação em dois toques); o campo tem Remover todas.
resume
Continuar de onde parou
- Guarda o disco, a posição na música e se ela estava ligada, a cada 4 segundos (
save-interval) e ao sair da página. - Ao recarregar, o mesmo disco volta selecionado e o player carrega logo depois da página. Os navegadores não deixam tocar som sozinho: a música continua no primeiro toque, clique ou tecla, do mesmo ponto.
- Se a pessoa desligou a música, ela não volta sozinha. Trocar de disco começa o novo do início.
- Disco-playlist volta no mesmo disco, com a ordem sorteada de novo.
- O ponto fica no navegador (
<storage-key>:point). Em sistemas com login, use uma chave por pessoa.
Exemplos para testar
Na janela de envio, o botão Exemplos mostra estes três vídeos longos: tocar num deles já preenche o link e envia. Para trocar a lista, use a opção examples; para tirar o botão, show-examples="false".
Sia · Unstoppable (Lyrics) · 30 MinGospel Lyrics · 29:58youtu.be/78kO0d0FxYo
Músicas internacionais românticas · anos 70, 80 e 90Música internacional romântica imortal · 1h15youtu.be/kDd2FhSeptY
Grupo Menos é Mais · Churrasquinho Menos é Mais 3 (DVD completo)Grupo Menos é Mais · 42 minyoutu.be/qPgwDlqdiD0
O primeiro tem 29:58, por isso a duração mínima padrão é mais de 25 minutos. Commin-duration="30", ele seria recusado com a mensagem de vídeo curto.
Músicas guardadas no seu servidor
Com storage: 'none', o navegador não guarda as músicas enviadas: o seu sistema salva na conta da pessoa (e elas aparecem em qualquer aparelho). onTrackAdd roda antes de guardar: devolva a música salva ou lance um erro com a mensagem para a pessoa. Confira de novo no servidor o id (/^[\w-]{11}$/) e a duração recebida.
import { createJukebox } from './metaphi-jukebox.js';
// sistema com login: as músicas enviadas ficam na conta da pessoa, no seu servidor
const jukebox = createJukebox({
tracks, // as músicas da casa
allowCustom: true, // botão "Adicionar música"
minDuration: 25, // só mixes e sets com mais de 25 minutos
maxCustom: 8, // ficam as 8 últimas
resume: true, // continuar de onde parou
storage: 'none', // o navegador não guarda as músicas: o servidor guarda
storageKey: `app:${user.id}`, // o ponto de parada, separado por pessoa
customTracks: await fetch('/api/musicas').then((r) => r.json()),
// salve e devolva a música (ou lance um erro: a mensagem aparece para a pessoa)
onTrackAdd: async (track) => {
const r = await fetch('/api/musicas', { method: 'POST', body: JSON.stringify(track) });
if (!r.ok) throw new Error('Não deu para salvar agora. Tente de novo.');
return r.json();
},
onTrackRemove: (id) => fetch('/api/musicas', { method: 'DELETE', body: JSON.stringify({ id }) }),
});05
API JavaScript
O próprio elemento é a API: document.querySelector('metaphi-jukebox') ou o retorno de createJukebox(). Tocar e trocar de disco precisam acontecer dentro de um clique ou toque, por causa das regras de som dos navegadores.
| Método / propriedade | Descrição |
|---|---|
play(index?) | Toca o disco index (posição ou id) ou o atual. Chame dentro de um clique/toque. |
pause() | Desliga a música (conta como "a pessoa desligou"). |
toggle() | Liga ou desliga. |
next() / previous() | Próximo / disco anterior, já tocando. |
setVolume(0–100) | Volume. 0 desliga. |
seek(segundos) | Vai para um ponto da música atual. |
hold() / release() | Pausa enquanto outro vídeo ou áudio da página toca e volta depois, sem contar como "a pessoa desligou". |
open() / close() | Abre ou fecha o painel de discos. |
prepare() | Carrega o player do YouTube agora, sem tocar. |
addTrack(link) | Confere e adiciona uma música. Promise { track, removed, duplicate }; erro com a mensagem pronta para mostrar. |
removeTrack(id) | Remove uma música enviada. Promise true/false. |
clearCustomTracks() | Remove todas as músicas enviadas. Promise com a quantidade. |
clearResume() | Esquece o ponto guardado (continuar de onde parou). |
update(opções) | Troca opções ao vivo. Aparência, leque e reprodução mudam sem recriar nada. |
destroy() | Desmonta tudo (também acontece ao remover o elemento da página). |
state | Leitura: { index, track, playing, status, volume, time, duration, open, held, ready }. |
tracks · options · version | Leitura: as músicas na ordem do leque, as opções atuais e a versão. |
06
Eventos
Disparados no elemento, com bubbles e composed: dá para ouvir no próprio elemento ou no document. O painel Ao vivo, no topo, mostra cada um acontecendo.
| Evento | Descrição |
|---|---|
jukebox:ready | O player do YouTube ficou pronto. |
jukebox:status | detail.status: playing, paused, waiting ou error. |
jukebox:play / jukebox:pause | O som começou ou parou de verdade (confirmado pelo player). |
jukebox:trackchange | Trocou de disco. detail: { index, track, playing, status, volume }. |
jukebox:open / jukebox:close | O painel abriu ou fechou. |
jukebox:trackadd | Entrou uma música enviada. detail: { track, removed }. |
jukebox:trackremove | Saiu uma música enviada. detail.id (null: todas). |
jukebox:update | Opções trocadas. detail.changed: a lista. |
07
Vídeos na página
Se a página tem vídeos ou áudios próprios, a música sai da frente enquanto eles tocam. hold() pausa sem contar como "a pessoa desligou"; release() volta, se ela não tiver desligado nesse meio-tempo.
const jukebox = document.querySelector('metaphi-jukebox');
const video = document.querySelector('video');
// o vídeo da página toca: a música pausa; parou: a música volta (se a pessoa não tiver desligado)
video.addEventListener('play', () => jukebox.hold());
video.addEventListener('pause', () => jukebox.release());
video.addEventListener('ended', () => jukebox.release());08
Estilo
O componente usa Shadow DOM: o CSS do site não quebra o toca-discos, e o dele não vaza. As cores vêm das opções (accent, surface, ink); as fontes, as partes internas e o estado ficam abertos para o site.
/* fontes do site dentro do componente (herdam para o Shadow DOM) */
metaphi-jukebox {
--jukebox-font: 'Inter', sans-serif;
--jukebox-font-mono: 'Geist Mono', monospace;
--jukebox-font-display: 'Archivo', sans-serif;
}
/* partes internas */
metaphi-jukebox::part(panel) { box-shadow: 0 40px 120px -40px #000; }
/* o site reage à música */
body:has(metaphi-jukebox[data-playing]) .equalizer { animation-play-state: running; }data-playing,data-open,data-readyedata-statusficam no próprio elemento.- Cliques dentro de elementos com
data-jukebox-keep-opennão fecham o painel (como o Customize desta página). - Quem prefere menos movimento (
prefers-reduced-motion) vê o leque sem animação e o disco parado.
10
Perguntas frequentes
A música pode parar de tocar sozinha?
Pode, nos discos do YouTube: o vídeo pode sair do ar, ficar privado, ter a incorporação desativada pelo dono, ser bloqueado por direitos autorais ou por país. O componente pula para o próximo disco (até 3 seguidos). O mais seguro é usar músicas sem direitos autorais ("No Copyright") ou mídia própria (src).
A música continua com a tela bloqueada ou em outra aba?
Com mídia própria e background, sim, com os controles do sistema na tela de bloqueio. Com o YouTube, não no celular: o navegador pausa o player quando a página sai da tela, e a música volta quando a pessoa retorna.
Por que a música não começa sozinha ao abrir a página?
Os navegadores não deixam uma página tocar som sem um gesto da pessoa. O componente toca dentro do próprio clique ou toque. Com autoplay, a música começa no primeiro clique, toque ou tecla em qualquer lugar da página (como nesta página); com "continuar de onde parou", ela volta do mesmo ponto nesse primeiro gesto.
Funciona no iPhone?
Sim. No celular o player carrega logo depois da página, para o primeiro toque já tocar. Se o Safari ainda pedir outro gesto, o botão de som pisca (estado waiting) e o próximo toque toca. As playlists passam de uma faixa à outra dentro do player, sem precisar de outro toque.
Apareceu "Ouvir no YouTube". O que houve?
O YouTube não tocou: vídeo indisponível, incorporação desativada pelo dono (erros 101 e 150) ou a checagem anti-robô do YouTube. Com skipErrors, o componente tenta o próximo disco antes de mostrar o link.
Preciso de uma chave da API do YouTube?
Não. A duração, o título e o canal das músicas enviadas vêm do próprio player incorporado, e o controle é feito por postMessage, sem o script da API.
Posso colar um link de playlist do YouTube (list=…)?
Não pelo campo de envio. Para tocar várias faixas em sequência, crie um disco com playlist: ["id1", "id2", …].
Funciona com Content Security Policy?
Sim. Libere frame-src https://www.youtube.com https://www.youtube-nocookie.com e img-src https://i.ytimg.com (e, se quiser o canal das músicas enviadas, connect-src https://www.youtube.com). Nenhum script do YouTube é carregado, e os estilos entram por adoptedStyleSheets e CSSOM, sem precisar de unsafe-inline.
O que fica guardado no aparelho da pessoa?
Por padrão, nada. Com allowCustom e storage: "local", as músicas enviadas ficam no localStorage (<chave>:tracks). Com resume, o disco, a posição e se a música estava ligada (<chave>:point). O player do YouTube segue as regras de cookies do YouTube quando carrega. No celular, por padrão, ele usa o domínio youtube-nocookie.com.
Como troco as músicas da playlist?
Crie um disco com playlist: a lista dos vídeos (ids ou links do YouTube), mais title, subtitle e, de preferência, uma cover própria. Ele toca as músicas em sequência, sorteando a ordem (shuffle). Links de playlist do YouTube (list=…) não servem: liste os vídeos um a um.
Achei um bug ou tenho uma ideia. Onde aviso?
Escreva para jukebox@metaphi.tech com o navegador, o aparelho e, se der, o link da página onde aconteceu.
Como uso em React, Next.js ou Vue?
Crie com createJukebox() num efeito que roda só no navegador (useEffect, onMounted) e chame .remove() ao desmontar. No Next.js, use o componente só no cliente. A aba "Código" do painel Ao vivo já gera o exemplo em React.
11
Licença e créditos
Uso livre: você pode usar, copiar, modificar e distribuir, inclusive em projetos comerciais, desde que mantenha o aviso de copyright e o texto da licença (o comentário no topo do arquivo, com os créditos). O componente é fornecido como está, sem garantia. O arquivo publicado é minificado e ofuscado; o código-fonte não é distribuído.
- Licença
- Licença MIT
MIT - Autor
- Deivison Arthur
- deivison@metaphi.tech
- linkedin.com/in/deivisonarthur
- Site
- metaphi.tech
- Bugs e melhorias
- jukebox@metaphi.tech
O texto completo da licença e os créditos estão no cabeçalho do arquivo (comentário /*! … */), que acompanha todas as cópias: mantê-lo é a condição da licença. O ícone de link no painel de discos leva para esta página.