如何将元数据和音轨从shoutcaststream中分离出来,而不用单独请求元数据和stream媒体

我制作了一个无线电应用程序,效果很好。 我可以播放广播stream并获取元数据。 stream媒体服务来自shoutcast

唯一的问题是,我将url作为数据源添加到媒体播放器,然后每5秒钟获取标题和艺术家。

有没有什么办法,我可以做一个HTTP请求,然后拆分audio和元数据,然后将其发送到媒体播放器?

获取元数据的代码。

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; } 

并将url传递给媒体播放器的数据源

 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(); } 

Solutions Collecting From Web of "如何将元数据和音轨从shoutcaststream中分离出来,而不用单独请求元数据和stream媒体"

你试图达成的任务并不容易。 (这不是不可能的。)stream的元数据仅在stream的开始处被“下载”,所以之后改变它将不会读取从stream中“caching”的元信息。 要阅读新的属性,你必须重新启动stream,这将获取新的标题等(但它可能会导致stream中断,所以它不被推荐)。

在声音技术中,使用水印是很常见的。 这是一个过程,你可以通过一些不是(质量)破坏的方式来丰富你的声音。 ( 在youtube上使用。 )Altogh很难做到,有一些方法可以隐藏你的信息在stream中。 我build议阅读这个来达到你想达到的目标。

由于您的硬件是手机,并不是所有的Android设备都足够强大,您应该考虑一些新的http请求。 在CPU,内存等方面,audio处理并不是一件便宜的事情。如果你这样做的话,还有一些其他的select需要考虑。 五秒轮询不是获取信息的最佳方式,因为你可以向用户显示虚假信息,虚假信息比没有更糟。 我推荐一个基于mqtt的服务器端推送。 这是一个很好的例子。 基于此方法的轮询scheme使用更less的stream量,更准确。