sarbagyastha / youtube_player_flutter

A Flutter plugin for inline playback or streaming of YouTube videos using the official iFrame Player API.
https://youtube.sarbagyastha.com.np
BSD 3-Clause "New" or "Revised" License
692 stars 784 forks source link

[BUG] Audio playing first with video delayed from black screen #541

Open a-l-l-a-n opened 3 years ago

a-l-l-a-n commented 3 years ago

When I play the youtube video, the audio of the video plays fine but the video is first black and comes a few seconds later . But both the video and audio are in sync. But the video appear visually later in the screen.

Can you help me with this bug?

I get these logs while playing... create MediaCodec video decoder, mime video/x-vnd.on2.vp9

I/OMXClient(10555): IOmx service obtained
I/MediaCodec(10555): MediaCodec will operate in async mode
D/SurfaceUtils(10555): connecting to surface 0x7766a22010, reason connectToSurface
I/MediaCodec(10555): [OMX.qcom.video.decoder.vp9] setting surface generation to 10808328
D/SurfaceUtils(10555): disconnecting from surface 0x7766a22010, reason connectToSurface(reconnect)
D/SurfaceUtils(10555): connecting to surface 0x7766a22010, reason connectToSurface(reconnect)
I/ExtendedACodec(10555): setupVideoDecoder()
I/ExtendedACodec(10555): Decoder will be in frame by frame mode
D/SurfaceUtils(10555): set up nativeWindow 0x7766a22010 for 480x854, color 0x7fa30c06, rotation 0, usage 0x20002900
W/MapperHal(10555): buffer descriptor with invalid usage bits 0x2000
I/chatty  (10555): uid=10314(np.com.sarbagyastha.youtube_player_iframe_example) CodecLooper identical 4 lines
W/MapperHal(10555): buffer descriptor with invalid usage bits 0x2000
D/SurfaceUtils(10555): set up nativeWindow 0x7766a22010 for 480x854, color 0x7fa30c06, rotation 0, usage 0x20002900
W/MapperHal(10555): buffer descriptor with invalid usage bits 0x2000
W/MapperHal(10555): buffer descriptor with invalid usage bits 0x2000
D/NdkImageReader(10555): acquireImageLocked: Overriding buffer format YUV_420_888 to 0x7fa30c06.
W/MapperHal(10555): buffer descriptor with invalid usage bits 0x2000
I/chatty  (10555): uid=10314(np.com.sarbagyastha.youtube_player_iframe_example) CodecLooper identical 1 line
W/MapperHal(10555): buffer descriptor with invalid usage bits 0x2000
W/AudioManager(10555): Use of stream types is deprecated for operations other than volume control
W/AudioManager(10555): See the documentation of requestAudioFocus() for what to use instead with android.media.AudioAttributes to 
qualify your playback use case

Edit1: The audio with delayed video issue doesn't happen when I turned on the youtube controls. It only happens if I turned off youtube controls.

PcolBP commented 3 years ago

Could you share sample of your code? I think that you refresh Iframe so theres your delay with black screen. Please also fill information about which package do you use.

a-l-l-a-n commented 3 years ago

@PcolBP Here's the code. I'm using a pageview and for each page I'm passing a link and creating a new youtube player widget. The audio with delayed video, issue does not happen if I enable youtube controls. It only happens if I disable youtube controls.

Here's the code

import 'dart:developer';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart';

import 'widgets/meta_data_section.dart';
import 'widgets/play_pause_button_bar.dart';
import 'widgets/player_state_section.dart';
import 'widgets/source_input_section.dart';
import 'widgets/volume_slider.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(YoutubeApp());
}

///
class YoutubeApp extends StatelessWidget {
  var link = [
    "xKT3deiaLEk",
    "gtm7m4tLUn0",
    "xKT3deiaLEk",
    "gtm7m4tLUn0",
  ];
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Youtube Player IFrame Demo',
      theme: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.deepPurple,
        scaffoldBackgroundColor: Colors.black,
      ),
      debugShowCheckedModeBanner: false,
      home: PageView.builder(
        scrollDirection: Axis.horizontal,
        controller: PageController(),
        itemBuilder: (BuildContext context, int itemIndex) {
          return YoutubeAppDemo(link[0]);
        },
      ),
    );
  }
}

///
class YoutubeAppDemo extends StatefulWidget {
  final _link;
  YoutubeAppDemo(this._link);
  @override
  _YoutubeAppDemoState createState() => _YoutubeAppDemoState();
}

class _YoutubeAppDemoState extends State<YoutubeAppDemo> {
  late YoutubePlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = YoutubePlayerController(
      initialVideoId: widget._link,
      params: const YoutubePlayerParams(
        playlist: [],
        startAt: const Duration(minutes: 0, seconds: 0),
        showControls: true,
        showFullscreenButton: true,
        desktopMode: false,
        privacyEnhanced: true,
        useHybridComposition: false,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    const player = YoutubePlayerIFrame();
    return YoutubePlayerControllerProvider(
      // Passing controller to widgets below.
      controller: _controller,
      child: Scaffold(
        body: LayoutBuilder(
          builder: (context, constraints) {
            return ListView(
              children: [
                Stack(
                  children: [
                    player,
                    const Controls(),
                  ],
                ),
              ],
            );
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.close();
    super.dispose();
  }
}

///
class Controls extends StatelessWidget {
  ///
  const Controls();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _space,
          // MetaDataSection(),
          _space,
          //  SourceInputSection(),
          _space,
          PlayPauseButtonBar(),
          _space,
          //VolumeSlider(),
          _space,
          // PlayerStateSection(),
        ],
      ),
    );
  }

  Widget get _space => const SizedBox(height: 10);
}
PcolBP commented 3 years ago

After copying your code and test, problem not occur. Player plays as it should, haven't notice black screen. Only blinking of widgets below. So it may be problem on your side.

a-l-l-a-n commented 3 years ago

@PcolBP It's doesn't happen often. But It occurs. If you keep testing repeatedly for 10 times , this issue happens one time on a real device. I've only used page view other than the plugin. Do you think the issue is on my phone only ?

PcolBP commented 3 years ago

@a-l-l-a-n it really rare cases when problem depends on phone. I think the problem is on platform_view and holding state. I also had problems with black screen on my side, solved it already but it was connected with holding controller state. Pageview has this to itself that its frees from resources a widget that you don't see and render new when when you will eneter it. Have you tried to add Key to in this case YoutubeAppDemo?

a-l-l-a-n commented 3 years ago

@PcolBP I don't know a lot about keys. Thanks for you reply. Can you suggest some keys to try in Pageview ? I'm just a real beginner

PcolBP commented 3 years ago

In that case I belieave that you dont need to get access to context of widget so use UniqueKey()

YoutubeAppDemo(
            link[0],
            key: UniqueKey(),
          );
 YoutubeAppDemo(
    this._link, {
    Key? key,
  }) : super(key: key);
a-l-l-a-n commented 3 years ago

@PcolBP Really appreciate your time for answering. I've tried it and no luck. I'll figure some other way out. Thanks