MyGo 云音乐
用 Go 与 MyGo 写成的第三方网易云音乐桌面客户端。原生界面,没有 WebView;边下边播,无损与 Hi-Res,逐字歌词与「律动」,刘海播放器。
Translation pending
Pads de som de baixa latência no navegador, feitos para o iPhone. Pastas por situação, sons próprios salvos no aparelho, funciona offline.
Translation pending
MediaJavaScript · CSSGitHub @RuanSantos01OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Pads de som que tocam no instante do toque, direto no navegador — incluindo o Safari do iPhone. No iPhone: abra esse endereço no Safari e faça Compartilhar → Adicionar à Tela de Início. Vira um app em tela cheia que funciona offline. O terminal mostra dois endereços: um para este Mac e um para o iPhone (precisa estar no mesmo Wi-Fi). Não há dependências nem build — é HTML, CSS e JS puros, então o que roda local é exatamente o que está publicado. Publicar uma mudança é só git push: o GitHub Pages serve a branch main.Read the full README ↗
Pads de som que tocam no instante do toque, direto no navegador — incluindo o Safari do iPhone.
No ar em https://ruansantos01.github.io/SoundPad/
No iPhone: abra esse endereço no Safari e faça Compartilhar → Adicionar à Tela de Início. Vira um app em tela cheia que funciona offline.
node serve.mjs
O terminal mostra dois endereços: um para este Mac e um para o iPhone (precisa estar no mesmo Wi-Fi). Não há dependências nem build — é HTML, CSS e JS puros, então o que roda local é exatamente o que está publicado.
Publicar uma mudança é só git push: o GitHub Pages serve a branch main.
Eles ficam no IndexedDB, no navegador daquele aparelho. Três riscos, em ordem de probabilidade:
Contra os dois primeiros o app pede navigator.storage.persist() ao abrir. Medido no
Safari do iOS (simulador, iPhone 16 Pro):
| Como o app foi aberto | persist() |
|---|---|
| Aba normal do Safari | negado |
| Ícone na Tela de Início (standalone) | concedido |
Ou seja: adicionar à Tela de Início é o que protege os sons, não só conforto de tela cheia. Quando o pedido é negado e existem sons próprios carregados, o app mostra um aviso.
Contra o terceiro risco (limpeza manual, ou apagar o ícone) não há API que ajude — só uma cópia dos arquivos originais resolve.
O iOS abre toda página com o áudio suspenso, e suspende de novo toda vez que o app vai para segundo plano (trocar de app, ligação, bloquear a tela). O indicador ao lado do título fica cinza quando isso acontece.
O toque seguinte resolve, e o som desse toque sai — não é um toque desperdiçado. Isso
exigiu cuidado: medido no Safari do iOS, com o contexto suspenso o start() não toca nada
e o onended nunca dispara, ou seja, a voz é descartada em silêncio. Como resume()
é assíncrono, "retomar e tocar na linha seguinte" era uma corrida que às vezes perdia — era
essa a causa do som falhar de forma intermitente.
Hoje o trigger() dispara na hora quando o contexto está de pé, e quando não está,
destrava dentro do gesto e só solta a voz depois que o contexto volta.
Cada pasta é uma situação — uma live, um podcast, um set — com 16 pads próprios.
A barra logo abaixo do título lista as pastas; o + cria mais.
← e → trocam de pasta.disparo — toca até o fimsegurar — toca enquanto o dedo estiver no padloop — toca em ciclo; o segundo toque desliga1234 QWER ASDF ZXCV tocam os 16 pads.Para montar uma pasta de 16 sons sem repetir o mesmo caminho 16 vezes: Editar → toque no nome da pasta → Carregar vários sons… → selecione tudo de uma vez. Os arquivos entram nos pads vazios, na ordem, e o nome de cada pad vira o nome do arquivo. Pads que já têm som são preservados. Se sobrarem arquivos além dos 16 pads, o app diz quantos ficaram de fora; se algum arquivo não puder ser lido, ele diz qual.
A pasta "Bateria" vem com 16 sons sintetizados pelo próprio navegador — nenhum arquivo para baixar. Seus arquivos (MP3, M4A, WAV, AAC) ficam salvos no aparelho, no IndexedDB, e voltam sempre que você reabrir.
Web Audio API com o áudio já decodificado na memória. Um <audio>.play() no iOS
custa de dezenas a centenas de milissegundos; AudioBufferSourceNode.start() dispara no
próximo bloco de áudio.
Evento touchstart, não click. O iOS só emite click no fim do toque, e com
atraso. Medido aqui: 0,2 ms entre o toque e o disparo.
latencyHint: 'interactive' pede ao sistema o menor buffer de saída possível.
Não forçamos navigator.audioSession.type. A tentação é usar 'playback' para
tocar com a chavinha de silencioso ligada. Medido no Safari do iOS, com dois contextos
novos e idênticos:
audioSession | estado | tocou |
|---|---|---|
auto (padrão) | running | sim, imediato |
playback | interrupted | não |
O buffer de saída é o mesmo nos dois (2,7 ms): 'playback' simplesmente derruba a
sessão. Preço de ficar no padrão: com o silencioso ligado o iOS pode calar o som —
se um pad não sair, confira a chavinha lateral.
O limitador é um WaveShaper, não um DynamicsCompressor. Medido nos dois motores, o compressor custa 6 ms de atraso na entrada e 6 ms de cauda depois que a fonte para — ele atrasa tudo para antecipar picos. O WaveShaper satura amostra a amostra: zero atraso, zero cauda, e ainda segura pico de 2,5 em 0,93.
O que sobra é a latência do próprio hardware de saída. Entre em Editar para ver o número
do seu aparelho — o app mostra saída ~N ms. Alto-falante ou fone com fio ficam na casa
de 10–40 ms; fone Bluetooth costuma somar 150–300 ms, e nenhuma linha de código muda isso.
index.html | estrutura da tela |
app.js | motor de áudio, pastas, pads, toque, persistência |
styles.css | visual |
sw.js + manifest.webmanifest | instalação na tela de início e uso offline |
serve.mjs | servidor local para testar no iPhone |
vercel.json | cabeçalhos do deploy na Vercel (ver abaixo) |
O app é estático: qualquer host serve. Hoje está no GitHub Pages, publicado a cada
git push na main.
O vercel.json existe para três coisas que quebram um PWA se ficarem no padrão:
sw.js sem cache. Se o service worker vier de cache, uma versão antiga do app fica
presa no aparelho e nenhum deploy novo chega.manifest.webmanifest com application/manifest+json. Sem o tipo certo o iOS
ignora o manifest e o "Adicionar à Tela de Início" perde nome e ícone.app.js / styles.css revalidando sempre. Os nomes não têm hash, então sem isso o
navegador segura a versão velha.Atenção ao trocar de endereço: cada domínio tem seu próprio armazenamento. Os sons
ficam no IndexedDB, que é por origem — o que você carregou em github.io não aparece em
vercel.app. Escolha um endereço e fique nele.