Extracting Metadata from HLS stream(m3u8 file)

anz picture anz · Oct 16, 2013 · Viewed 8.9k times · Source

I have a requirement where I need to extract metadata from an HLS Stream in Android. I have found two libraries FFMPEG and VITAMIO. Considering the fragmented support of HLS streaming on android, and after reading a plethora of even more confusing articles, I have finalized the above two libraries for further research.I have not found a single application where the extraction of metadata(timed metadata) has been done on Android.

I am confused if it is even possible on Android. And if so,which approach should I use... help me out guys....

Answer

Nikola Despotoski picture Nikola Despotoski · Oct 21, 2013

Parsing m3u8 is relatively easy. You need to create HashMap of String and Integer to store parsed data. M3U8 file is composed of 3 entry tags which represent the entry of the m3u8, media sequence and the segment duration of all media files, except the last one, which differs from the rest.

After each #EXTINF integer duration is sticked to it, so we need to get this by parsing the string with basic regex.

private HashMap<String, Integer> parseHLSMetadata(InputStream i ){

        try {
            BufferedReader r = new BufferedReader(new InputStreamReader(i, "UTF-8"));
            String line;
            HashMap<String, Integer> segmentsMap = null;
            String digitRegex = "\\d+";
            Pattern p = Pattern.compile(digitRegex);

            while((line = r.readLine())!=null){
                if(line.equals("#EXTM3U")){ //start of m3u8
                    segmentsMap = new HashMap<String, Integer>();
                }else if(line.contains("#EXTINF")){ //once found EXTINFO use runner to get the next line which contains the media file, parse duration of the segment
                    Matcher matcher = p.matcher(line);
                    matcher.find(); //find the first matching digit, which represents the duration of the segment, dont call .find() again that will throw digit which may be contained in the description.
                    segmentsMap.put(r.readLine(), Integer.parseInt(matcher.group(0)));
                }
            }
            r.close();
            return segmentsMap;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

Cheers.