iArt.ai
AI 모션 그래픽 소프트웨어, 누구나 사용할 수 있는 After Effects 대안, 텍스트 프롬프트로 몇 분 안에 애니메이션·설명 영상 제작
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Radios Viferor Radios y podcast 1.28.0 · APK 1.15.0 — Que no se ponga a sonar solaREADME 전문 보기 ↗
Radios y podcast
El registro del 23-10 a las 17:22 lo dejó claro: con el APK 1.16.1 ya instalado seguían
saliendo PIPELINE_ERROR_READ… y sin ninguna línea MUSIC_IO. O sea: la app ya servía el
archivo entero y correcto. El que se rompía era el lector del WebView, que va pidiendo
trozos al archivo y da el error por bueno aunque tenga 100 s cargados por delante (por eso
Poweramp, que lee el archivo directamente, nunca fallaba).
MUSIC_IO.Pista clave del usuario: Poweramp reproduce esos mismos archivos sin cortarse nunca. Si un reproductor nativo va bien y el nuestro no, el archivo está bien y el fallo está en cómo lo leemos nosotros.
LocalMusic leía el audio con
AssetFileDescriptor.createInputStream(), que corta la lectura en la longitud que declara
MediaStore (que puede estar desfasada) y además salta el principio del archivo por su
cuenta. Si esa longitud se queda corta, el cuerpo de la respuesta termina antes de lo que
dice la cabecera Content-Length y Chromium lo denuncia como
PIPELINE_ERROR_READ: data source error a mitad de canción — incluso con datos de sobra
en el búfer (así salía en el registro) y con play() colgado hasta 34 s. Ahora se lee el
descriptor del archivo directamente y se busca con el canal (FileInputStream +
getChannel().position()): se llega siempre al final real del archivo.MUSIC_IO con el archivo y los números. Sirve para
saber si el problema está al servir el archivo (nuestro lado) o en el reproductor del
WebView (el decodificador de Chromium).El registro del 23-10 (16:15) enseñó dos cosas que sí dependían de la web:
se vuelve a cargar… intento=1/2, luego intento=2/2 y después
play() rechazado al recargar: AbortError). Ahora solo hay una recuperación a la vez.error 3, el .m4a de «Catalina» a los 2,49 s): se
reintentaban en el mismo segundo, cosa que no arregla nada. Ahora, si el problema es
decodificar, se salta el trozo (10 s) directamente y, si tampoco, se pasa a la
siguiente canción. Si el fallo es de leer pero ocurre en los primeros 5 s, se pasa
a la siguiente en vez de empezar la canción por el minuto 0:20 (antes no se podía leer el
archivo entero).play() sin esperar (eso era lo que dejaba la
música muda): si no se puede recuperar, se sigue con otra canción.rs, ns y el código de
error del reproductor, para saber qué pasó exactamente.Sin APK 1.16.0 no aparecen líneas
MUSIC_IOen el registro, y son justo las que dicen por qué falla la lectura del archivo (tamaño que no cuadra, reapertura, byte).
El registro del móvil del 23-10 enseñó lo que pasaba: la canción fallaba al leer el archivo
(PIPELINE_ERROR_READ) en el segundo 186, el reintento en la otra platina también fallaba en
el mismo punto y, como la cola estaba vacía, la música se quedaba parada hasta que se
pulsaba «anterior».
gan=0.00 en el registro) ahora se devuelve el volumen al darle a ▶, al pausar y en el
cambio de platina. Y la platina nueva de la recuperación se sube solo cuando play()
responde, así que no se oyen dos canciones a la vez.tam=) cuando no se puede
reproducir, para poder compararlo con el tamaño real (lo apunta la APK nueva como
MUSIC_IO).La causa del corte está en la parte nativa: para que la lectura del archivo no falle hace falta el APK 1.16.0. Si en el registro no aparece ninguna línea
MUSIC_IO, el móvil sigue con una APK anterior.
MainActivity pedía a la
web «vuelve a la última sección» en cada arranque y la pedía dos veces (a los
1,8 s y a los 3,5 s), sin distinguir un arranque normal de un toque en el widget: si
estabas en Música y tocabas Radios, a los pocos segundos volvía a Música; y al volver a
la app desde otra pestaña, también. Ahora:
openSection). Un arranque normal no fuerza nada.radios_viferor_last_tab_v1) y la vuelve a
poner una sola vez al abrir (restaurarPestanaAlAbrir()).switchToMusic() sin argumentos) se ignoran:
ya no pueden devolverte a una pestaña que no has pedido.Android.lastPlaybackSection()), así que al actualizar no se pierde la costumbre.play() sin esperar: salía «la recarga no arrancó (AbortError)» y la canción volvía al
segundo 0 (o se saltaba a la siguiente). Ahora se carga en la otra platina, en el
punto donde iba, y cuando ya tiene datos se cambia a ella sin pausar nada.waiting/stalled) más de
8 s, se recupera sola igual. Antes solo se apuntaba en el registro y la música se
quedaba muda.PIPELINE_ERROR_READ), la longitud solo se declara si se sabe y, si una lectura
falla, se vuelve a abrir el archivo en el punto donde iba y se sigue leyendo.MUSIC_IO (tamaño que no cuadra, reapertura, byte donde falló), para saber la próxima
vez si es del archivo, de MediaStore o del reproductor.PIPELINE_ERROR_READ en /__music/track/…):
la misma canción fallaba en el segundo 53 y volvía a sonar bien después. Antes, al primer
fallo se avisaba y se saltaba a la siguiente. Ahora se vuelve a cargar la misma canción en
el punto donde iba (dos intentos por minuto, para no entrar en bucle si el archivo está
roto de verdad) y solo se salta si tampoco arranca.readyState=1, networkState=2, tal y como salía en el registro). Esa recarga era el
corte de sonido. Ahora, mientras el archivo se está cargando, se le da tiempo (hasta 20 s
más) y no se toca nada. También se fuerza una lectura de verdad al recargar: si la dirección
es la misma, el navegador no volvía a leer el archivo.buf=) y el
estado del reproductor, para saber por qué falló la próxima vez.audioState()); aviso corto
(≤ 45 s) → vuelve; otra app que sigue sonando más de 45 s → queda en pausa. Se puede
desactivar en Ajustes: «Volver a sonar tras una llamada o aviso».En la pantalla principal de cada pestaña, deslizar en horizontal cambia de pestaña como un carrusel (igual que la carátula de una canción): a la izquierda pasa a la de la derecha (Radios → Podcasts → Música) y a la derecha, a la de la izquierda. Ahora incluye Música (en su pantalla principal, sin búsqueda ni detalle abierto) y no reacciona al deslizar sobre las pestañas de Mi música, los reproductores ni los menús.
La app aparece en «Abrir con…» y «Compartir» de cualquier archivo de audio (MP3, M4A, FLAC, OGG/Opus, WAV…) y de las listas M3U/M3U8, desde el gestor de archivos, WhatsApp, Telegram, Drive… Android pregunta con qué app abrirlo; eligiendo Radios Viferor y «Siempre» queda como reproductor predeterminado de esos tipos.
OpenAudioActivity (invisible) recibe el archivo y se lo pasa a la ventana de la app sin
abrir otra copia; ExternalAudio lee nombre, tamaño, etiquetas, duración y carátula./__music/ext/{ficha} (con Range),
con su carátula en /__music/extart/{ficha} y título/artista desde las etiquetas o el nombre.Menú ⋯ de una canción → ✏️ Editar nombre y etiquetas…: cambia el nombre del archivo
(la extensión se conserva) y, en MP3, las etiquetas ID3 (título, artista, álbum, artista del
álbum, pista, disco, año y género). Ayudas: «Etiquetas desde el nombre» (07 - Artista - Título) y «Nombre desde las etiquetas». Solo se envía lo que cambia.
En la APK (MusicEditor + Id3Editor): Android 11+ pide permiso para modificar el archivo
(createWriteRequest); Android 10 con RecoverableSecurityException; 9 o anterior con
WRITE_EXTERNAL_STORAGE. Las etiquetas se reescriben conservando todo lo demás (carátula,
letra, comentarios…) y la versión ID3 del archivo (2.3 en UTF-16 o 2.4 en UTF-8); si la nueva
cabe en el hueco de la antigua se escribe encima y, si no, se reescribe el archivo copiando el
audio tal cual. La ID3v1 del final, si existe, se pone al día. Después MediaStore vuelve a
leer el archivo. Si la canción suena, se suelta mientras se guarda y sigue donde iba.
En 🎚️ Sonido, 🔀 Según por dónde suena (activado por defecto en la app Android 1.12+):
el ecualizador, la corrección de auriculares, el balance y el mono se recuerdan por salida
—altavoz del móvil, auriculares con cable, USB y cada dispositivo Bluetooth por su nombre—
y se cambian solos al conectar o desconectar (aviso en pantalla). Un Bluetooth nuevo cuyo
nombre coincide con unos auriculares conocidos (p. ej. realme Buds Air 7 Pro) estrena con su
corrección; el resto empieza plano. Las salidas guardadas se ven en la tarjeta y se pueden
olvidar. La APK avisa de los cambios con AudioDeviceCallback (en Android 13+ con la ruta
real de la música; antes, Bluetooth > cable > altavoz).
Menú ⋯ de Mi música → ⏱ Buscar canciones cortas o rotas…: lista las canciones que duran menos de lo que elijas (5 s, 15 s, 30 s, 1 min, 2 min u otra duración, en segundos o m:ss), de la más corta a la más larga, incluidas las que no tienen duración. Debajo de cada una sale la ruta del archivo; se pueden reproducir, guardar como lista, exportar sus rutas a .txt u ocultar su carpeta.
En el reproductor de música ampliado, deslizar el dedo a la izquierda pone la canción anterior y a la derecha, la siguiente. La carátula sigue al dedo; un gesto corto o vertical no hace nada, y tocar la carátula sigue abriendo la letra.
/api/similar), mismo género y época, con más peso para tus
favoritas y las más escuchadas, y sin repetir artista seguido. Es una radio sin fin:
cuando quedan pocas canciones añade más. Reproducir otra colección la desactiva.La pestaña 💡 Significado ya no depende de encontrar la letra: si no la hay (o LRCLIB falla), la IA explica la canción a partir del título, el artista y el álbum, y avisa si no la conoce en vez de inventar. Desde «No se ha encontrado la letra» hay un botón «💡 Ver el significado».
Cuando LRCLIB tardaba o devolvía un error puntual, la búsqueda de letra fallaba con «LRCLIB no responde». Ahora el servidor reintenta, lanza a la vez la búsqueda exacta y la de artista+título y solo da error si fallan todas; y si nuestro servidor no consigue respuesta, la app pregunta a LRCLIB directamente desde el móvil.
Al salir de la app, Android avisaba al WebView de que su ventana dejaba de verse; Chromium marcaba la página como oculta y reajustaba el audio, lo que producía un corte muy breve. Ahora, mientras hay algo sonando (servicio de reproducción activo), el WebView ignora ese aviso y el sonido sigue sin interrupción. Solo cambia la app Android.
Botón 🎚️ Sonido en el reproductor de música (y en el ⋯ de Mi música).
Motor. Dos <audio> (platinas): la siguiente canción se precarga 15 s antes y entra sin
pausa al acabar la actual, o con fundido entre canciones (2–12 s). Fundido corto al pausar
y reanudar (sin chasquidos). Los eventos solo cuentan para la platina que suena.
Cadena de Web Audio (ecualizador.js, solo se crea al activar algo, tras un toque):
mono → preamp → corrección de auriculares (hasta 20 filtros) → ecualizador de 10 bandas →
nivelador (compresión suave) → balance → limitador (−1 dB) → volumen. Preamp automático para no
saturar y curva de respuesta.
Ecualizador: 16 presets (graves, voz, rock, electrónica, flamenco y acústica, volumen bajo…)
y presets propios. Auriculares: correcciones de AutoEq
(MIT, curva Harman). Incluidos los Realme Buds Air 7 Pro con y sin cancelación de ruido
(medición de Regan Cipher); el resto, unos 9.000 modelos, con /api/autoeq (índice y
ParametricEQ.txt de GitHub). Ajustes en radios_viferor_music_audio_v1.
API. El plan gratuito de Vercel admite 12 funciones: letras, traducción, significado, publicar
y AutoEq van en una sola, api/music.js, que reparte según vercel.json (las rutas
/api/lyrics, /api/translate… no cambian). Los manejadores están en api/_*.js.
Favoritos (radios_viferor_music_favs_v1): canciones (menú ⋯ o «☆ Favorita» en el
reproductor), álbumes, artistas, carpetas y géneros (botón ☆ en su cabecera o en su menú ⋯).
Pestaña ⭐ Favoritos con todo lo marcado y botones para escucharlo junto; las listas
inteligentes tienen el origen «Mis favoritos».
Carpetas (radios_viferor_music_folders_v1): en Carpetas, «⚙️ Incluir / excluir carpetas»
abre el árbol de todas las carpetas (también las ocultas). 🚫 Excluir oculta una carpeta y lo de
dentro en toda la música (canciones, álbumes, artistas, búsqueda, listas inteligentes); ✅ Incluir
hace que solo se vea lo de las incluidas; se combinan. También desde el ⋯ de cada carpeta. Se
aplica al momento, sin volver a leer el móvil; las listas normales y la cola siguen pudiendo
tener canciones de carpetas ocultas.
GEMINI_FALLBACK_MODELS). Si en Vercel hay además
ANTHROPIC_API_KEY, la usa como último recurso. vercel.json da 60 s a esa función./api/lyrics-publish). El
dispositivo resuelve el reto de LRCLIB (SHA-256 en Web Workers) y se publica con el desfase
aplicado.En «Mi música», botón 🎤 Letra (reproductor ampliado o ⋯ de cualquier canción).
De dónde sale. Por orden: tu versión (pegada, elegida o sincronizada; se guarda en
radios_viferor_lyrics_user_v1, entra en el backup), la incrustada en el archivo (USLT/©lyr;
en el móvil se lee solo la etiqueta ID3 del principio con Range), un .lrc con el mismo nombre
al lado de la canción (navegador) y LRCLIB vía /api/lyrics (caché en IndexedDB).
Sincronizada: la línea que suena se ilumina y se centra; tocar una línea salta a ella. «Ajustar desfase» la adelanta o retrasa. Sin sincronizar: «⏱ Sincronizar» pone la canción desde el principio y se toca MARCAR al empezar cada línea (descuenta 0,2 s de reacción, «Deshacer», barra espaciadora en el PC) y se guarda como LRC; o «Buscar versión sincronizada» elige entre las de LRCLIB. También: editar o pegar la letra (texto o .lrc), exportar .lrc.
Original + español: traducción automática línea a línea (/api/translate, Google, sin
clave), debajo de cada línea. Ahí está 💡 Significado de la canción (/api/song-meaning):
qué quiso transmitir el autor, temas e imágenes y contexto, explicado por IA. Necesita una
clave: GEMINI_API_KEY (gratis en aistudio.google.com/apikey) o ANTHROPIC_API_KEY en las
variables de Vercel, o pegarla en la app (se guarda solo en el dispositivo). Modelos:
GEMINI_MODEL (por defecto gemini-3.6-flash) y ANTHROPIC_MODEL (claude-haiku-5-5).
Tercera pestaña, 🎵 Música: reproductor de la música guardada en el dispositivo.
De dónde sale la música. En la app Android (APK 1.10.0 o posterior) se pide el permiso
«Música y audio» y se leen las canciones registradas en el móvil (MediaStore). El WebView
intercepta tres rutas de la app: /__music/library.json, /__music/track/{id} (con Range,
para poder saltar) y /__music/art/{álbum} (LocalMusic.java). Nada sale del móvil. En el
navegador del PC se elige una carpeta: en Chrome/Edge se recuerda; las etiquetas y carátulas
se leen con jsmediatags (vendor/) y se guardan en IndexedDB. Con un APK antiguo, la pestaña
pide actualizar la app.
Ver por canciones, álbumes, artistas, carpetas (con migas de pan) y géneros, con búsqueda por palabras. En cada álbum, artista, carpeta o género: reproducir, aleatorio, a continuación, a la cola, guardar en lista o crear una lista inteligente. Menú ⋯ en cada canción (ir al álbum, artista o carpeta, información, veces escuchada).
Reproductor. Mini y ampliado, aleatorio, repetir (todo / una), cola reordenable, historial, temporizador, volumen. Notificación y pantalla de bloqueo con anterior/siguiente (sección «music» en la parte nativa); en el PC, teclas multimedia. Solo suena una cosa a la vez: radio, podcast o música.
Listas. Normales (reordenar, quitar, ordenar) e inteligentes (artistas, álbumes, carpetas o géneros; nunca escuchadas, más escuchadas, olvidadas; añadidas hace poco; duración; años; orden y máximo) con plantillas. Exportar e importar en M3U (VLC, Poweramp…) o JSON. Se cuentan las escuchas (a los 30 s o a la mitad).
Claves: radios_viferor_music_* (cola, historial, opciones, listas, estadísticas, posición).
Debajo de «Mis podcasts» hay un botón «Mis listas» que despliega el orden de las suscripciones, los modos (Últimos de todas, Mezclar, Continuar, Populares) y los accesos a la Cola y a las Listas. «Mis podcasts» abre directamente tus suscripciones en el orden elegido.
Cola. Lo que suena después del episodio actual. Se guarda al cerrar la app y se ve en ☰ Cola (portada, «Mis podcasts» o el reproductor ampliado). Se reordena arrastrando ⠿, se mezcla, se vacía, se guarda como lista y se quitan los escuchados (todo con «Deshacer»). Opciones: repetir (episodio o cola entera), pasar al siguiente solo, saltar escuchados y, al acabar la cola, seguir con novedades de tus suscripciones. ⏮ vuelve al principio si llevas más de 10 s; si no, al episodio anterior del historial.
Episodios. Cada episodio tiene «+ Cola» y un menú ⋯: reproducir ahora, a continuación, al final de la cola, añadir a una lista, marcar como escuchado o no, ir al podcast. En cada podcast, «☰ Cola y listas…» añade de golpe los sin escuchar (del más antiguo al más nuevo) o crea una lista inteligente solo con ese podcast. «Últimos de todas», «Mezclar» y «Continuar» ya no borran tu cola: si tienes una, preguntan si sustituirla, ponerlos a continuación o al final.
Listas. Normales (eliges los episodios y el orden) e inteligentes (reglas: qué podcasts —suscripciones, favoritos, una categoría o los que elijas—, sin escuchar / sin terminar / empezados, fecha, duración mínima y máxima, cuántos por podcast, máximo y orden, incluido «alternando podcasts»). Plantillas: novedades de la semana, cortos, a medias, lo nuevo de favoritos, mezcla sorpresa. Se reproducen, se ponen a continuación o al final, se duplican, se ordenan, se exportan e importan (JSON) y una inteligente se puede fijar como lista normal. Las copias de seguridad completas ya las incluyen.
Reproductor. Velocidad (0,75× a 2,5×, se recuerda) y temporizador para dormir (minutos o al terminar el episodio). Muestra cuál es el siguiente de la cola.
Código: podcast-listas.js (pantallas, listas, menús) y el núcleo de la cola en podcasts.js.
Claves nuevas: radios_viferor_podcast_queue_v2, …_history_v1, …_queue_opts_v1,
…_playlists_v1, radios_viferor_podcast_speed.
Versión. Para publicar una versión nueva de la web: node scripts/version.mjs 1.7.3 1730
(actualiza version.js y las marcas ?v= de index.html, para que el móvil no mezcle scripts
antiguos de su caché con los nuevos). La de Android está en app/build.gradle
(versionName / versionCode). «Buscar actualizaciones» compara la versión en uso con el
version.js publicado.
Radio. Reconexión con espera creciente (2, 4, 8… hasta 60 s, máximo 8 intentos) y sin carreras al cambiar rápido de emisora. Pausar ya no provoca reconexiones, y la canción y la programación solo se consultan mientras suena. Reordenar favoritas arrastrando ya no se corta. Cargar favoritas añade sin duplicados.
Podcasts. La posición se guarda cada 5 s mientras suena. «Continuar» reproduce lo que dejaste
a medias. «Mis podcasts» hace como mucho 4 peticiones ligeras a la vez. Los episodios sin
<guid> tienen un identificador estable. «Reanudar al abrir» es opcional (en Ajustes).
API. /api/metadata, /api/podcast-feed y /api/podcast-audio ya no aceptan direcciones
internas ni privadas, validan cada redirección y limitan las peticiones por IP
(api/_lib/net.js). /api/podcast-feed admite ?meta=1 y ?limit=N.
Android. Servicio en primer plano mientras suena, para que Android no corte el audio en segundo plano. Los avisos de nuevos episodios usan JobScheduler y abren el podcast correcto. El WebView solo navega por la app. Atrás en la pantalla principal manda la app a segundo plano.
APK. GitHub Actions compila el APK en cada cambio de app/
(pestaña Actions → APK Android → artefacto radios-viferor-apk).
tests/smoke/run.ps1