Quantcast
Channel: Active questions tagged youtube-api - Stack Overflow
Viewing all articles
Browse latest Browse all 3638

Youtube Data API v3 - How to insert a video using Flutter/Dart?

$
0
0

I want to create a project in Flutter where I can record videos with my phone and upload them directly to my YouTube account using the videos.insert method from YouTube Data API. I managed to get all the required authentifications and have access to the YouTube Data API (I tested it with other API calls and it worked without any issues) but I am stuck with videos.insert method.

Here is my code so far:

    Video video = new Video();    video.snippet = new VideoSnippet();    video.snippet!.title = "Default Video Title";    video.snippet!.description = "Default Video Description";    video.snippet!.tags = ["tag1", "tag2" ];    video.snippet!.categoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list    video.status = new VideoStatus();    video.status!.privacyStatus = "unlisted"; // or "private" or "public"    var filePath = ""; // Replace with path to actual movie file.    var stream = new File(filePath).readAsString();    var httpClient = (await _googleSignIn.authenticatedClient())!;    var youTubeApi = YouTubeApi(httpClient);    var videosInsertRequest = youTubeApi.videos.insert(video, ["snippet", "status"]);

I couldn't find any examples of Dart code on Google and I am new to programming in Dart/Flutter - how should I read the video file and where do I need to insert it in my code for the request to be completed? if I try to add my stream or filePath variable as another parameter to my videos.insert - I will get an exception that says I have too much arguments. In other examples that I found on Google(YouTube Data API v3 documentation) was a code example in .NET where the filePath was just another parameter for the videos.insert but here in Dart it doesn't seem to be the same and I am having a hard time understanding how it actually works.

To be more specific in the YouTube Data API V3 documentation the insert example is the following:

youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");

As we can see its very simple. Now in Dart this is where I am stuck:

youTubeApi.videos.insert(video, ["snippet", "status"]);

As you can see I added the video object, the "snippet, status" string list but when I try to add a third argument fileStream I will get the "too many arguments" message exception.

This is the videos.insert method in Dart:

Future<Video> Function(Video, List<String>, {String? $fields, bool? autoLevels, bool? notifySubscribers, String? onBehalfOfContentOwner, String? onBehalfOfContentOwnerChannel, bool? stabilize, Media? uploadMedia, UploadOptions uploadOptions})

UPDATE 1:

When I call the insert.video request nothing happens. Here is my current full code right now:

import 'package:googleapis/youtube/v3.dart' as YT;var httpClient = (await _googleSignIn.authenticatedClient())!;var youTubeApi = YT.YouTubeApi(httpClient);YT.Video video = new YT.Video();video.snippet = new YT.VideoSnippet();video.snippet!.title = "Default Video Title";video.snippet!.description = "Default Video Description";video.snippet!.tags = ["tag1", "tag2" ];video.snippet!.categoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/listvideo.status = new YT.VideoStatus();video.status!.privacyStatus = "unlisted"; // or "private" or "public"var status = await Permission.storage.status;if (!status.isGranted) {  await Permission.storage.request();}Stream<List<int>> stream = new File("/storage/emulated/0/Download/video.mp4").openRead();int length = await stream.length;var media = new YT.Media(stream, length);var videosInsertRequest = youTubeApi.videos.insert(video, ["snippet", "status"], uploadMedia: media);videosInsertRequest.timeout(Duration(seconds: 60));videosInsertRequest.then((value) => {print("THEN")});videosInsertRequest.whenComplete(() => {print("COMPLETED")});videosInsertRequest.onError((error, stackTrace) => _handleError());

The Video, Media object are from googleapis/youtube/v3.dart package.

I tried so far:

  • re-create AVD android phone emulator
  • wipe all data
  • cold boot the emulator
  • added <uses-permission android:name="android.permission.INTERNET"/> to AndroidManifest.xml - ( I have internet on the emulated device, I can open google/youtube and watch videos etc.)
  • disable my VPN
  • verify my internet connection
  • checked video file on local player - its playable and valid

Other googleapis requests work ex. getting playlists. If I don't set a timeout exception then the request just hangs without any response - not even from Android Studio... what am I doing wrong? My internet connection is solid, cable internet and the AVD emulator device has working internet as well. Again, idk if this is the issue because I get no response from YouTube API no matter how long I wait.

Another part that I suspect is the length of the media file where I set it at int length = await stream.length; - could please someone confirm that I am doing it the right way here?

These are my scopes:

GoogleSignIn _googleSignIn = GoogleSignIn(  scopes: <String>[YT.YouTubeApi.youtubeReadonlyScope, YT.YouTubeApi.youtubeUploadScope],);

The app asks to read and manage my YouTube account videos and I grant the request in the android emulator. No issues here.

UPDATE 2

If I set null to the uploadMedia I will get an exception of Invalid Argument but the meta data contained in the video param will be uploaded to my YouTube account. It looks like its something related with the uploadMedia file.

var videosInsertRequest = youTubeApi.videos.insert(video, ["snippet", "status"], uploadMedia: null);

So with this the new video will be created on YouTube with the title, description etc. but without the actual media file.

Update 3 - IT WORKS!!!

I changed 2 things in the above code:

  • media file type: I don't know why it didn't wanted to work with mp4 files but with .avi files started working
  • media length variable from int length = await stream.length; to int length = await new File("/storage/emulated/0/Download/video4.avi").length();

Here is my full working code with Google Sign In:

import 'dart:async';import 'dart:io';import 'package:flutter/material.dart';import 'package:google_sign_in/google_sign_in.dart';import 'package:googleapis/youtube/v3.dart' as YT;import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';import 'package:permission_handler/permission_handler.dart';GoogleSignIn _googleSignIn = GoogleSignIn(  scopes: <String>[YT.YouTubeApi.youtubeReadonlyScope, YT.YouTubeApi.youtubeUploadScope],);void main() {  runApp(    MaterialApp(      title: 'Google Sign In',      home: SignInDemo(),    ),  );}class SignInDemo extends StatefulWidget {  @override  State createState() => SignInDemoState();}class SignInDemoState extends State<SignInDemo> {  GoogleSignInAccount? _currentUser;  String _contactText = '';  late Future<YT.Video> videosInsertRequest;  @override  void initState() {    super.initState();    _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount? account) async {      setState(() {        _currentUser = account;      });      if (_currentUser != null) {        print("User logged in!");      }    });    _googleSignIn.signInSilently();  }  Future<void> _handleSignIn() async {    try {      await _googleSignIn.signIn();    } catch (error) {      print(error);    }  }  Future<void> _handleVideoInsert() async {    var httpClient = (await _googleSignIn.authenticatedClient())!;    var youTubeApi = YT.YouTubeApi(httpClient);    YT.Video video = new YT.Video();    video.snippet = new YT.VideoSnippet();    video.snippet!.title = "Default Video Title";    video.snippet!.description = "Default Video Description";    video.snippet!.tags = ["tag1", "tag2" ];    video.snippet!.categoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list    video.status = new YT.VideoStatus();    video.status!.privacyStatus = "private"; // or "private" or "public"    var status = await Permission.storage.status;    if (!status.isGranted) {      await Permission.storage.request();    }    Stream<List<int>> stream = new File("/storage/emulated/0/Download/video4.avi").openRead();    int length = await new File("/storage/emulated/0/Download/video4.avi").length();    YT.Media media = new YT.Media(stream, length);    print("Insert in progress...");    videosInsertRequest = youTubeApi.videos.insert(video, ["snippet", "status"], uploadMedia: media);    //videosInsertRequest.timeout(Duration(seconds: 60));    videosInsertRequest.then((value) => {print("THEN")});    videosInsertRequest.whenComplete(() => {print("COMPLETED")});    videosInsertRequest.onError((error, stackTrace) => _handleError());    print(video.status!.uploadStatus);  }  FutureOr<YT.Video> _handleError() async {    print("Error");    return new YT.Video();  }  Future<void> _handleSignOut() => _googleSignIn.disconnect();  Widget _buildBody() {    GoogleSignInAccount? user = _currentUser;    if (user != null) {      return Column(        mainAxisAlignment: MainAxisAlignment.spaceAround,        children: <Widget>[          ListTile(            leading: GoogleUserCircleAvatar(              identity: user,            ),            title: Text(user.displayName ?? ''),            subtitle: Text(user.email),          ),          const Text("Signed in successfully."),          Text(_contactText),          ElevatedButton(            child: const Text('SIGN OUT'),            onPressed: _handleSignOut,          ),          ElevatedButton(            child: const Text('UPLOAD'),            onPressed: () { print("Upload button pressed!"); _handleVideoInsert(); },          ),        ],      );    } else {      return Column(        mainAxisAlignment: MainAxisAlignment.spaceAround,        children: <Widget>[          const Text("You are not currently signed in."),          ElevatedButton(            child: const Text('SIGN IN'),            onPressed: _handleSignIn,          ),        ],      );    }  }  @override  Widget build(BuildContext context) {    return Scaffold(        appBar: AppBar(          title: const Text('Google Sign In'),        ),        body: ConstrainedBox(          constraints: const BoxConstraints.expand(),          child: _buildBody(),        ));  }}

Thank you for the help! I hope it will help someone in the future. Also as a note for the above code to work you still need to configure your project in Google's Console and give the appropriate API's permissions explained here: https://flutter.dev/docs/development/data-and-backend/google-apis


Viewing all articles
Browse latest Browse all 3638

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>