1
votes

I'm trying to develop an android app in which the user can upload a video from the device to my YouTube channel.

I'm stuck on OAuth2 authentication using Youtube Data API v3. I've found code for enable the user to select their own account and use to authenticate, but it is not what I want.

How can it be done?

Thanks in advance.

1

1 Answers

2
votes

If you mean uploading from users' mobile/browser client side directly to Youtube server directly, yes, it can be done totally. It took me a quite a few days to figure out the tricks though.

The step is a bit complicated.


Step 1. You need to register an "YouTube Data API v3" app on Google.

https://console.developers.google.com/project

Get there and create a project. Then go to "APIS" and enable "YouTube Data API v3".

You also need to get your client ID and client secret for the next step.

And don't forget to set the "redirect_uri" on "YouTube Data API v3" API console to "http://YOURWEBSITE.com/get_refresh_token.php".


Step 2. You need a refresh token from youtube. In most "youtube upload client side" tutorial, they teach you how to upload to the channel of users themseleves, but not to the channel on your own. In order to achieve this tricky function, what you need is a refresh token.

In order to gain the refresh token, you need to put this php file on your own server/website, and run it for a single time. Name the file "get_refresh_token.php" and put it on your website. Its url must match the "redirect_uri" mentioned in last step.

<?php 
if(isset($_GET['code'])) {
    $code = $_GET['code'];
    $url = 'https://accounts.google.com/o/oauth2/token';
    $params = array(
        "code" => $code,
        "client_id" => "CLIENT ID GET FROM GOOGLE",
        "client_secret" => "CLIENT SECRET GET FROM GOOGLE",
        "redirect_uri" => "http://YOURWEBSITE.com/get_refresh_token.php",
        "grant_type" => "authorization_code"
    );

    echo getOnlineData($url, $params);
} else {
    $params = array(
        "response_type" => "code",
        "client_id" => "CLIENT ID GET FROM GOOGLE",
        "redirect_uri" => "CLIENT SECRET GET FROM GOOGLE",
        "scope" => "https://www.googleapis.com/auth/youtube",
        "access_type" => "offline"
        );

    $request_to = "https://accounts.google.com/o/oauth2/auth?".http_build_query($params);

    header("Location: " . $request_to);
}

function getOnlineData($url, $post_arr) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_AUTOREFERER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);

    if($post_arr) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_arr));
    }

    $temp_data = curl_exec($ch);
    curl_close($ch);
    return $temp_data;
}
?>

Login with the account of your channel. Then finally you will get a long string. Find the "refresh_token" and save it on your database, safely.


Step 3. Now you have the refresh_token right? Then everytime when users need to upload a video to your channel, your app need to call your server for the access_token. All you need to do is to convert the "refresh_token" into a juicy refresh access_token by below code.

<?php
$url = "https://accounts.google.com/o/oauth2/token";
$params = array(
    "client_id" => "CLIENT ID GET FROM GOOGLE",
    "client_secret" => "CLIENT SECRET GET FROM GOOGLE",
    "refresh_token" => "REFRESH TOKEN STORED IN DATABASE A LONG TIME AGO",
    "grant_type" => "refresh_token"
);

$temp_data = getOnlineData($url, $params);
$temp_json = json_decode($temp_data);

echo $temp_json->access_token;
?>

Step 4. Alright now you have the "access_token", then all you need to do is pass it to client side (your app).

Now you've got everything you need. Let the magic happens(javascript part)

var file = $('#VIDEO').get(0).files[0];
var token = 'THE TOKEN RETRIEVED FROM SERVER SIDE"

var metadata = {
    snippet: {
        title: "TITLE OF THE VIDEO",
        description: "DESCR OF THE VIDEO",
        categoryId: 22
    },
    status: {
        privacyStatus: "public",
        license: "youtube"
    }
};

$.ajax({
    url: 'https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status',
    method: 'POST',
    contentType: 'application/json',
    headers: {
        Authorization: 'Bearer ' + token,
        'x-upload-content-length': file.size,
        'x-upload-content-type': file.type
    },
    data: JSON.stringify(metadata)
}).done(function(data, textStatus, jqXHR) {
    resumableUpload({
        url: jqXHR.getResponseHeader('Location'),
        file: file,
        start: 0
    });
})

function resumableUpload(options) {
    $.ajax({
        url: options.url,
        method: 'PUT',
        contentType: options.file.type,
        headers: {
            'Content-Range': 'bytes ' + options.start + '-' + (options.file.size - 1) + '/' + options.file.size
        },
        xhr: function() {
            var xhr = $.ajaxSettings.xhr();

            if(xhr.upload) {
                xhr.upload.addEventListener('progress', function(e) {
                    if(e.lengthComputable) {
                        var bytesTransferred = e.loaded;
                        var totalBytes = e.total;
                        var percentage = Math.round((100*bytesTransferred/totalBytes));

                        if(percentage >= 100) percentage = 99;

                        $('#td_submit').text("Video Uploading on "+percentage+"%");
                    }
                }, false);
            }
            return xhr;
        },
        processData: false,
        data: options.file
    }).done(function(response) {        
        alert("Your video's URL is https://www.youtube.com/watch?v="+response.id);
    })
}

After that, you can see all processing video on

https://www.youtube.com/my_videos?o=U.