¿Cómo puedo separar los metadatos y la pista de un flujo de shoutcast sin realizar solicitudes separadas de metadatos y el streaming
He hecho una aplicación de radio que funciona perfectamente bien. Soy capaz de reproducir el flujo de radio y buscar los metadatos también. El servicio de streaming es de shoutcast.
El único problema es que, estoy agregando la url como la fuente de datos para el reproductor de medios y luego buscar el título y el artista cada 5 segundos.
- Obtención de metadatos de SHOUTcast utilizando IcyStreamMeta
- Estado de reproducción de Android MediaPlayer
- Reproducir desde Shoutcast Url en android
- Solicitud de Android SHOUTcast
- ¿Cómo resolver "reproductor multimedia Android detener automáticamente después de algún tiempo en streaming"?
¿Hay alguna manera, sólo puedo hacer una solicitud http y luego dividir el audio y los metadatos y luego enviarlo al reproductor multimedia?
Código para obtener metadatos.
private void retreiveMetadata() throws IOException { int metaDataOffset = 0; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .addHeader("Icy-MetaData", "1") .addHeader("Connection", "close") .addHeader("Accept", "") .url(streamUrl) .build(); request.headers(""); Response response = client.newCall(request).execute(); InputStream stream = response.body().byteStream(); //Map<String, List<String>> headers = response..getHeaderFields(); if (!response.headers("icy-metaint").equals("")) { // Headers are sent via HTTP String icyMetaInt = response.headers("icy-metaint").toString(); icyMetaInt = icyMetaInt.replace("[", ""); icyMetaInt = icyMetaInt.replace("]", ""); metaDataOffset = Integer.parseInt(icyMetaInt); } else { // Headers are sent within a stream StringBuilder strHeaders = new StringBuilder(); char c; while ((c = (char)stream.read()) != -1) { strHeaders.append(c); if (strHeaders.length() > 5 && (strHeaders.substring((strHeaders.length() - 4), strHeaders.length()).equals("\r\n\r\n"))) { // end of headers break; } } // Match headers to get metadata offset within a stream Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n"); Matcher m = p.matcher(strHeaders.toString()); if (m.find()) { metaDataOffset = Integer.parseInt(m.group(2)); } } // In case no data was sent if (metaDataOffset == 0) { isError = true; return; } // Read metadata int b; int count = 0; int metaDataLength = 4080; // 4080 is the max length boolean inData = false; StringBuilder metaData = new StringBuilder(); // Stream position should be either at the beginning or right after headers while ((b = stream.read()) != -1) { count++; // Length of the metadata if (count == metaDataOffset + 1) { metaDataLength = b * 16; } if (count > metaDataOffset + 1 && count < (metaDataOffset + metaDataLength)) { inData = true; } else { inData = false; } if (inData) { if (b != 0) { metaData.append((char)b); } } if (count > (metaDataOffset + metaDataLength)) { break; } } // Set the data metadata = IcyStreamMeta.parseMetadata(metaData.toString()); // Close stream.close(); } public static Map<String, String> parseMetadata(String metaString) { Map<String, String> metadata = new HashMap(); String[] metaParts = metaString.split(";"); Pattern p = Pattern.compile("^([a-zA-Z]+)=\\'([^\\']*)\\'$"); Matcher m; for (int i = 0; i < metaParts.length; i++) { m = p.matcher(metaParts[i]); if (m.find()) { metadata.put((String)m.group(1), (String)m.group(2)); } } return metadata; }
Y pasando la url a la fuente de datos del reproductor multimedia
String url = "http://68.68.109.106:8356/"; mp = new MediaPlayer(); mp.setAudioStreamType(AudioManager.STREAM_MUSIC); try { mp.setDataSource(url); mp.prepare(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); } catch (SecurityException e) { // TODO Auto-generated catch block Log.e(TAG, "SecurityException"); Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); } catch (IllegalStateException e) { // TODO Auto-generated catch block Log.e(TAG, "IllegalStateException"); Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); } catch (IOException e) { // TODO Auto-generated catch block Log.e(TAG, "IOException"); Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); }
- Código androide para streaming shoutcast stream breaks en 2.2
- Recibir información de un flujo de ShoutCast en Android
- Transmisión de audio con Android MediaPlayer
- Cómo obtener el tipo de contenido de ShoutCast 7.html
- Icecast / shoutcast streaming en Android
- Android 2.2 MediaPlayer está funcionando bien con una URL de SHOUTcast, pero no con la otra
- ¿Cómo analizar una respuesta HTTP no estándar?
La tarea que intenta lograr no es algo que sea fácil de hacer. (Tho no es imposible.) Los metadatos de la corriente se descargan solamente "al principio de la corriente, así que cambiarla después no tendría ningún efecto que lee las metainformations" en caché "de la corriente. Para leer las nuevas propiedades tienes que reiniciar la secuencia, esto buscará los nuevos encabezados etc. (Pero podría causar una interrupción en la secuencia por lo que no es realmente recomendable.)
En tecnología de sonido es común utilizar marcas de agua . Es un proceso en el que enriquece su sonido con algún tipo de datos de la manera no destructiva (de calidad). ( Usage en youtube. ) Altogh es difícil de hacer, hay algunas maneras de ocultar su información en la corriente. Recomiendo leer esto para alcanzar la meta que desea alcanzar.
Debido a que su hardware es un teléfono móvil y no todos los dispositivos Android son lo suficientemente fuertes que debe considerar algunas nuevas solicitudes http. El procesamiento de audio no es una cosa barata hablar en términos de CPU, memoria, etc Hay algunas otras opciones a considerar si lo hace. La encuesta de cinco segundos no es la mejor manera de obtener la información, ya que podría mostrar información falsa al usuario y la información falsa es peor que nada. Recomiendo un empuje del lado del servidor basado en mqtt. Aquí hay un ejemplo bastante agradable del uso. Una solución basada en este método insted de la encuesta está usando menos tráfico y es más exacta.