Skip to content

iPhone SE (OS version - 15.7.3) - vimeo video showing black screen #2592

Open
@adityasethipsi

Description

@adityasethipsi

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Observed a strange behavior in iOS, where when I played the vimeo video, it was played. Then I changed the orientation between portrait and landscape, it was getting played. When I came back of the player, it showed black screen on video player, though audio was still coming.

iOS device - iPhone SE (OS version - 15.7.3)

Expected Behavior

It should show the video and audio in sync

Steps with code example to reproduce

String? _vimeoIframeData = '';
String? _videoId = '';
Widget _vimeoPlayerWidget = WaitScreen();

@OverRide
void initState() {
super.initState();

_getVimeoVideoData();
// _loadVimeoIframeData();

}

Widget _videoPlayerMobile({
String? iFrameCode,
String? videoId,
Key? key,
}) {
String? srcValue;
try {
var document = parse(iFrameCode ?? widget.videoUrl);
var element = document.getElementsByTagName('iframe').elementAtOrNull(0);
srcValue = element?.attributes['src'] ?? '';
} catch (e) {
print('Error while fetching IFrame src from vimeo video embeded code');
srcValue = null;
}

final isLoading = true.obs;
return ObxValue(
  (RxBool state) {
    return Stack(
      children: [
        AspectRatio(
          aspectRatio: 16 /
              ((srcValue != null && srcValue.isNotEmpty)
                  ? 10
                  : 11), // if there is direct player url available, then using aspectRatio as 16/10 , else using 16/11
          child: Stack(
            children: [
              state.value
                  ? WaitScreen(
                      bgColor: Colors.black.withValues(alpha: .3),
                    )
                  : const SizedBox(),
              Container(
                child: InAppWebView(
                  key: key,
                  initialSettings: InAppWebViewSettings(
                    mediaPlaybackRequiresUserGesture: false,
                    allowsInlineMediaPlayback: true,
                    useHybridComposition: true,
                  ),
                  initialData: InAppWebViewInitialData(
                    data: _buildHtmlContent(videoId),
                    baseUrl: WebUri("https://player.vimeo.com"),
                  ),
                  onConsoleMessage: (controller, consoleMessage) {
                    final message = consoleMessage.message;
                    if (message.startsWith('vimeo:')) {
                      _manageVimeoPlayerEvent(message.substring(6));
                    }
                  },
                  onWebViewCreated: (controller) {
                    widget.webViewController = controller;
                    widget.onInAppWebViewCreated?.call(controller);
                  },
                  onLoadStart: widget.onInAppWebViewLoadStart,
                  onLoadStop: (controller, url) {
                    isLoading.value = false;
                    widget.onInAppWebViewLoadStop?.call(controller, url);
                  },
                  onReceivedError: (controller, request, error) {
                    isLoading.value = false;
                    // onReceivedError will be called also for subframes
                    // which cause the dialog to display when there is no error
                    // in playing the video (Fix for MIN-11697)
                    if (!(request.isForMainFrame ?? true)) return;
                    
                  },
                  shouldOverrideUrlLoading:
                      (controller, navigationAction) async {
                    var uri = navigationAction.request.url;

                    // Allow Vimeo links to load
                    if (uri != null &&
                        uri.toString().contains("player.vimeo.com")) {
                      return NavigationActionPolicy.ALLOW;
                    }

                    // Block other external navigation (e.g., ads, redirects)
                    return NavigationActionPolicy.CANCEL;
                  },
                  onEnterFullscreen: widget.onEnterFullscreen,
                  onExitFullscreen: widget.onExitFullscreen,
                ),
                
              ),
            ],
          ),
        ),
      ],
    );
  },
  isLoading,
);

}

Future _getVimeoVideoData() async {
// fetch vimeo video id
String? vimeoVideoId;
if (widget.videoUrl.isNotEmpty && widget.videoUrl.contains('vimeo.com/')) {
var arr = widget.videoUrl.split('/');
if (arr.length > 1) {
vimeoVideoId = arr.elementAtOrNull(arr.length - 1);
}
}

// fetch vimeo IFrameData
var vimeoIframeData =
    await UtilityMethods().getVimeoPlayerIFrame(widget.videoUrl);

_setVideoData(
  vimeoVideoId,
  vimeoIframeData,
);

}

void _setVideoData(String? vimeoVideoId, String? vimeoIframeData) {
setState(() {
_videoId = vimeoVideoId ?? '';
_vimeoIframeData = vimeoIframeData;
_setVimeoPlayerWidget();
});
}

void _setVimeoPlayerWidget() {
_vimeoPlayerWidget = (_videoId ?? '').isNotEmpty
? _videoPlayerMobile(
iFrameCode: _vimeoIframeData,
videoId: videoId,
key: Key(
'embedCodeVideoPlayerMobileWidget
${base64Encode(utf8.encode(widget.videoUrl))}',
),
)
: WaitScreen();
}

String _buildHtmlContent(String? videoId) {
return '''



<style>
body {
margin: 0;
padding: 0;
background-color: #000000;
}
.video-container {
position: relative;
width: 100%;
height: 100vh;
}
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>

<script src="https://player.vimeo.com/api/player.js"></script>



<iframe id="player" src="${_buildIframeUrl(videoId ?? '')}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen webkitallowfullscreen mozallowfullscreen>
</iframe>

<script>
const player = new Vimeo.Player('player');
player.ready().then(() => console.log('vimeo:onReady'));
player.on('play', () => console.log('vimeo:onPlay'));
player.on('pause', () => console.log('vimeo:onPause'));
player.on('ended', () => console.log('vimeo:onFinish'));
player.on('seeked', () => console.log('vimeo:onSeek'));
</script>


''';
}

/// Builds the iframe URL
String _buildIframeUrl(String videoId) {
var iFrameURL = 'https://player.vimeo.com/video/$videoId?'
'autoplay=${widget.isAutoPlay}'
'&loop=${widget.isLooping}'
'&muted=${widget.isMuted}'
'&title=${widget.showTitle}'
'&byline=${widget.showByline}'
'&controls=${widget.showControls}'
'&dnt=${widget.enableDNT}';
return iFrameURL;
}

/// Manage vimeo player events received from the WebView
void _manageVimeoPlayerEvent(String event) {
debugPrint('Vimeo event: $event');
switch (event) {
case 'onReady':
widget.onReady?.call();
break;
case 'onPlay':
widget.onPlay?.call();
break;
case 'onPause':
widget.onPause?.call();
break;
case 'onFinish':
widget.onFinish?.call();
break;
case 'onSeek':
widget.onSeek?.call();
break;
}
}

Future _cleanupAndGoBack() async {
await widget.webViewController?.evaluateJavascript(source: '''
var iframe = document.querySelector("iframe");
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage('{"method":"pause"}', '*');
}
''');

await widget.webViewController?.loadData(
  data: "<html></html>",
  baseUrl: WebUri("about:blank"),
);

await Future.delayed(Duration(milliseconds: 100));
widget.webViewController?.dispose();
Get.back();

}

@OverRide
Widget build(BuildContext context) {
return PopScope(
canPop: true,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (didPop) {
_cleanupAndGoBack();
}
},
child: _videoId == null
? (widget.errorWidget ?? UIUtil().renderVideoErrorWidget())
: ((_videoId ?? '').isNotEmpty ? _vimeoPlayerWidget : WaitScreen()),
);
}

Stacktrace/Logs

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.27.4, on Microsoft Windows [Version 10.0.22621.4890], locale en-IN)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
[√] Chrome - develop for the web
[X] Visual Studio - develop Windows apps
X Visual Studio not installed; this is necessary to develop Windows apps.
Download at https://visualstudio.microsoft.com/downloads/.
Please install the "Desktop development with C++" workload, including all of its default components
[√] Android Studio (version 2024.1)
[√] VS Code (version 1.98.2)
[√] Connected device (3 available)
[√] Network resources

! Doctor found issues in 1 category.

Flutter version

3.27.4

Operating System, Device-specific and/or Tool

iOS device - iPhone SE (OS version - 15.7.3)

Plugin version

6.1.5

Additional information

No response

Self grab

  • I'm ready to work on this issue!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions