How to embed YouTube videos into Flutter app to start from a specified timestamp?

480 Views Asked by At

If you click on a YouTube video besides letting you copy the link, YouTube lets you to copy the link to start from the current time of playing. How can I do that on Flutter with YouTube embedded videos?

I used youtube_player_flutter and used YouTube URLs instead of video IDs, but even if I add a timestamp to the end of the links it still starts from the beginning. Is it possible to do it with this plugin? Is there another plugin capable of doing that?

import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,

      title: 'Flutter Example',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  static String videoId = 'BBAyRBTfsOU';

  static int startTime = 150;

  static String youtubeUrlWithStartTime =
      'https://www.youtube.com/watch?v=$videoId&t=$startTime';

  final YoutubePlayerController _controller = YoutubePlayerController(
    initialVideoId: videoId,
    flags: const YoutubePlayerFlags(
      autoPlay: true,
      mute: false,
    ),
  );

  MyHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter and Youtube'),
      ),
      body: YoutubePlayer(
        controller: _controller,
        liveUIColor: Colors.amber,
      ),
    );
  }
}
2

There are 2 best solutions below

2
CBroe On

You can use the startAt property in your YoutubePlayerFlags for that.

https://pub.dev/documentation/youtube_player_flutter/latest/youtube_player_flutter/YoutubePlayerFlags/startAt.html

startAt property.
int startAt.
final.
Specifies the default starting point of the video in seconds

Default is 0.

0
dutch On

Edit: I shared incorrect information last time.

I got this concept to work using a WebViewWidget() and ListView.builder(), making sure to define the WebView controler inside the builder method. I also had to use the embed urls rather than the regular share urls from YouTube.

Here's a working example that renders videos in a list view, where the videos start at 10, 92, and 110 seconds, respectively (Flutter 3.13.6 stable; worked on iOS emulator and physical iPhone running iOS 17.1):

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class VideoApp extends StatefulWidget {
  const VideoApp({super.key});

  @override
  VideoAppState createState() => VideoAppState();
}

class VideoAppState extends State<VideoApp> {

  final List<String> videoEmbedUrls = [
    'https://www.youtube.com/embed/_o7qjN3KF8U?si=M0yo4R94r_NaVjyQ&amp;start=10',
    'https://www.youtube.com/embed/y8OnoxKotPQ?si=EmT_Ellfthq1ORcq&amp;start=92',
    'https://www.youtube.com/embed/eSqexFg74F8?si=pi77XZW6oI4rbw_9&amp;start=110'
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Vehicle Data Entry')),
      body: SafeArea(
        child: ListView.builder(
          itemCount: 3,
          itemBuilder: (context, index) {
            var wvController = WebViewController()
              ..setJavaScriptMode(JavaScriptMode.unrestricted)
              ..setBackgroundColor(const Color(0x00000000))
              ..setNavigationDelegate(
                NavigationDelegate(
                  onProgress: (int progress) {
                    // Update loading bar.
                  },
                  onPageStarted: (String url) {},
                  onPageFinished: (String url) {},
                  onWebResourceError: (WebResourceError error) {},
                  onNavigationRequest: (NavigationRequest request) => NavigationDecision.navigate,
                ),
              );
            return Padding(
              padding: const EdgeInsets.all(8.0),
              child: SizedBox(
                height: 300,
                child: WebViewWidget(controller: wvController..loadRequest(Uri.parse(videoEmbedUrls[index])))
              ),
            );
          },
        ),
      ),
    );
  }
}