proxyM3u8Content function

M3u8 proxyM3u8Content(
  1. String content,
  2. String proxy(
    1. String raw
    ),
  3. Uri uri
)

According to the rfc8216 URI attribute values in #EXT-X-I-FRAME-STREAM-INF or #EXT-X-MEDIA tags are replaced by the absolute and proxied ones.

URI attribute values in #EXT-X-KEY, #EXT-X-SESSION-KEY, #EXT-X-SESSION-DATA or #EXT-X-MAP tags are replace by the absolute ones.

The contents of #EXT-X-STREAM-INF tags are replaced by the absolute and proxied ones.

The contents of #EXTINF tags are replaced by the absolute ones, if the m3u8 file contains a #EXT-X-ENDLIST, then the contents are also proxied at the same time.

Implementation

M3u8 proxyM3u8Content(String content, String Function(String raw) proxy, Uri uri) {
  bool isLive = !content.contains('#EXT-X-ENDLIST');
  String? tagName;
  M3u8 m3u8 = M3u8(content);
  String proxied = content.split('\n').map((line) {
    line = line.trim();
    if (line.startsWith('#EXT')) {
      int colonPos = line.indexOf(':');
      if (colonPos == -1) {
        tagName = line;
        return line;
      }
      tagName = line.substring(0, colonPos);
      if (tagName == '#EXT-X-KEY' || tagName == '#EXT-X-SESSION-KEY') {
        m3u8.encrypted = true;
      }
      if (tagName == '#EXT-X-MEDIA' ||
          tagName == '#EXT-X-STREAM-INF' ||
          tagName == '#EXT-X-I-FRAME-STREAM-INF' ||
          tagName == '#EXT-X-SESSION-DATA' ||
          tagName == '#EXT-X-SESSION-KEY') {
        m3u8.master = true;
      }
      if (tagName == '#EXT-X-I-FRAME-STREAM-INF' || tagName == '#EXT-X-MEDIA') {
        // m3u8 links
        // to absolute and proxy the URI
        return line.replaceFirstMapped(_tagURIRegex, (match) {
          String playlist = uri.resolve(match.group(1)!).toString();
          m3u8.playlists.add(playlist);
          return 'URI="${proxy(playlist)}"';
        });
      }
      if (tagName == '#EXT-X-KEY' || tagName == '#EXT-X-SESSION-KEY' || tagName == '#EXT-X-SESSION-DATA' || tagName == '#EXT-X-MAP') {
        // to absolute the URI
        return line.replaceFirstMapped(_tagURIRegex, (match) {
          return 'URI="${uri.resolve(match.group(1)!).toString()}"';
        });
      }
      return line;
    }
    if (line.isEmpty) {
      tagName = null;
      return line;
    }

    if (tagName == '#EXT-X-STREAM-INF') {
      tagName = null;
      // to absolute and proxy
      String playlist = uri.resolve(line).toString();
      m3u8.playlists.add(playlist);
      return proxy(playlist);
    }
    if (tagName == '#EXTINF') {
      tagName = null;
      // to absolute
      line = uri.resolve(line).toString();
      m3u8.playlists.add(line);
      if (isLive) {
        return line;
      }
      // proxy
      return proxy(line);
    }
    tagName = null;
    return line;
  }).join('\n');
  m3u8.proxied = proxied;
  if (!m3u8.master) {
    m3u8.endless = isLive;
  }
  return m3u8;
}