ja2375 / FluTube

A Flutter plugin to facilitate embedding Youtube videos inside mobile apps.
MIT License
34 stars 17 forks source link

Youtube not playing on iOS #22

Open ctippur opened 4 years ago

ctippur commented 4 years ago

Hello,

Not sure if anyone else has experienced this but the same youtube link plays on Android but on iOS, I get a spinning wheel. This seem to happen almost 75% of the time on iOS.

There are no errors. Can you please shed some light? It cant be a permission issue as the video plays some times.

Here is the code:

FluTube.playlist(
              vidURL,
              autoInitialize: true,
              aspectRatio: 16 / 9,
              allowMuting: false,
              showControls: true,
              looping: false,
              autoPlay: true,
              fullscreenByDefault: true,
              deviceOrientationAfterFullscreen: [
                DeviceOrientation.landscapeRight,
                DeviceOrientation.landscapeLeft,
              ],
              systemOverlaysAfterFullscreen: SystemUiOverlay.values,
              onVideoStart: () async {
                startActivity();
              },
              onVideoEnd: () async {
                onStop(context);
              },
            )

Appreciate your input.

Thanks, SHekar

ctippur commented 4 years ago

Here is the stack trace:

[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0

0 List.[] (dart:core-patch/growable_array.dart:147:60)

1 FluTubeState._fetchVideoURL

#2 FluTubeState._initialize package:flutube/src/flutube_player.dart:141 #3 FluTubeState.initState package:flutube/src/flutube_player.dart:133 #4 StatefulElement._firstBuild package:flutter/…/widgets/framework.dart:4068 #5 ComponentElement.mount package:flutter/…/widgets/framework.dart:3919 #6 Element.inflateWidget package:flutter/…/widgets/framework.dart:3101 #7 Element.updateChild package:flutter/…/widgets/framework.dart:2904 #8 SingleChildRenderObjectElement.mount package:flutter/…/widgets/framework.dart:5127 #9 Element.inflateWidget package:flutter/…/widgets/framework.dart:3101 #10 Element.updateChild (package:flutter/s<…>
ctippur commented 4 years ago

I think this maybe the issue. During a unsuccessful youtube url rendering, I see that the response body maybe either malformed or null. As a result, parseAll.toList()[0] doesnt seem to have anything in it.

Future<String> _fetchVideoURL(String yt) async {
    final response = await http.get(yt);
    Iterable parseAll = _allStringMatches(response.body, RegExp("\"url_encoded_fmt_stream_map\":\"([^\"]*)\""));
    final Iterable<String> parse = _allStringMatches(parseAll.toList()[0], RegExp("url=(.*)"));
    final List<String> urls = parse.toList()[0].split('url=');
    parseAll = _allStringMatches(urls[1], RegExp("([^&,]*)[&,]"));
    String finalUrl = Uri.decodeFull(parseAll.toList()[0]);
    if(finalUrl.indexOf('\\u00') > -1)
      finalUrl = finalUrl.substring(0, finalUrl.indexOf('\\u00'));
    return finalUrl;
  }
chethanprabhakar commented 4 years ago

Hi @ja2375

We are facing this issue continuously. Is it possible to respond?

Thanks in advance

gsabanti commented 4 years ago

There is simply no url_encoded_fmt_stream_map for this video. I face this issue too. Unfortunately, no solution yet.

gsabanti commented 4 years ago

I think I found the temporary solution. Edit this function and in my case it works. Not sure if it is the ultimate solution, but I've only got this one.

Not refactored!

  Future<String> _fetchVideoURL(String yt) async {
    final response = await http.get(yt);
    Iterable parseAll = _allStringMatches(response.body, RegExp("\"url_encoded_fmt_stream_map\":\"([^\"]*)\""));
    Iterable<String> parse;
    if (parseAll.toList().isEmpty) {
      parseAll = _allStringMatches(response.body, RegExp("streamingData.*]"));
      parse = _allStringMatches(parseAll.toList()[0], RegExp(r'"url\\":\\".*?\\"'));
      final List<String> urls = parse.toList()[0].split(r'":\');
      String finalUrl = Uri.decodeFull(urls[1].substring(1, urls[1].length - 2).replaceAll(r'\\u0026', '&').replaceAll(r'\/', r'/'));
      return finalUrl;
    } else {
      parse = _allStringMatches(parseAll.toList()[0], RegExp("url=(.*)"));
      final List<String> urls = parse.toList()[0].split('url=');
      parseAll = _allStringMatches(urls[1], RegExp("([^&,]*)[&,]"));
      String finalUrl = Uri.decodeFull(parseAll.toList()[0]);
      if(finalUrl.indexOf('\\u00') > -1)
        finalUrl = finalUrl.substring(0, finalUrl.indexOf('\\u00'));
      return finalUrl;
    }
  }
chethanprabhakar commented 4 years ago

@McFriend We will try this. Thanks

alanpachuau commented 4 years ago

@McFriend your temporary solution seems to be quite reliable. Thank you.

Recently, even i started receiving RangeError on parseAll.toList()[0] in this line


final Iterable<String> parse = _allStringMatches(parseAll.toList()[0], RegExp("url=(.*)"));

When I check the response body, none of the videos I have are returning "url_encoded_fmt_stream_map", but they all have "streamingData" though.