Upload Video to YouTube using PHP

YouTube is the most popular video-sharing website that allows users to upload, view, and share videos online. If your web application has video upload functionality and you want to reduce the space of your server, upload video to YouTube will be a great idea. By uploading videos on YouTube, you will get the following facilities.

  • Server space will not be consumed for video files.
  • Videos can be easily embedded on the web page.
  • Videos can be shared easily.

YouTube Data API provides an easy way to upload video to YouTube from the website using Google API Client Library. In this tutorial, we will show how you can upload video to YouTube from web application using PHP. Our example code will use the Google API PHP Client Library to upload video on YouTube from the website using PHP.

In the example YouTube video uploader script, the following functionality will be implemented.

  • HTML form to collect video title, description, tags, and file.
  • Upload video to YouTube from PHP script with title, description, tags, and privacy.
  • Embed uploaded YouTube video on the web page.

Before getting started to build a PHP script to upload video to YouTube using PHP OAuth library, take a look at the file structure.

upload_video_to_youtube_with_php/
├── config.php
├── dbConfig.php
├── index.php
├── upload.php
├── youtube_video_sync.php
├── status.php
├── logout.php
├── google-api-php-client/
└── videos/

Create Google Project and Enable YouTube Data API

You need to register your application on Google Developers Console for using Google API Client Library. Also, make sure the YouTube Data API v3 library is enabled to access YouTube data.

  • Go to the Google API Console.
  • Select an existing project from the projects list, or click NEW PROJECT to create a new project:
    • Type the Project Name.
    • The project ID will be created automatically under the Project Name field. (Optional) You can change this project ID by the Edit link, but it should be unique worldwide.
    • Click the CREATE button.
  • Select the newly created project and enable the YouTube Data API service.
    • In the sidebar, select Library under the APIs & Services section.
    • Search for the YouTube Data API v3 service in the API list and select YouTube Data API v3.
    • Click the ENABLE button to make YouTube Data API v3 Library available.
  • In the sidebar, select Credentials under the APIs & Services section.
    • Select the OAuth consent screen tab, specify the consent screen settings.
    • Enter the Application name.
    • Choose a Support email.
    • Specify the Authorized domains which will be allowed to authenticate using OAuth.
    • Click the Save button.
  • Select the Credentials tab, click the Create credentials drop-down and select OAuth client ID.
    • In the Application type section, select Web application.
    • In the Authorized redirect URIs field, specify the redirect URL.
    • Click the Create button.

A dialog box will appear with OAuth client details, note the Client ID and Client secret for later use in the script. This Client ID and Client secret allow you to access the Google YouTube Data API.

youtube-data-google-api-console-client-id-secret-codexworld

Note that: The Client ID and Client secret need to be specified at the time of Google API call. Also, the Authorized redirect URIs must be matched with the Redirect URL specified in the script.

Do you want a detailed guide on Google project creation? See this tutorial – How to Create Google API Console Project

Google API Client Library for PHP

The Google API Client Library helps to authenticate with Google account and access the YouTube Data API using PHP. All the required Google API Client Library files are placed in the google-api-php-client directory.

Create Database Table

To store the video information a table is required in the database. The following SQL creates a videos table with some basic fields in the MySQL database.

CREATE TABLE `videos` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` text COLLATE utf8_unicode_ci DEFAULT NULL,
  `tags` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `privacy` enum('public','private') COLLATE utf8_unicode_ci NOT NULL,
  `file_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `youtube_video_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Google API and Database Configuration (config.php)

In the config.php file, constant variables of the Google OAuth API Client and database settings are defined.
Database Constants:

  • DB_HOST – Specify the database host.
  • DB_USERNAME – Specify the database username.
  • DB_PASSWORD – Specify the database password.
  • DB_NAME – Specify the database name.

Google OAuth Client Constants:

  • OAUTH_CLIENT_ID – Specify the OAuth Client ID of the Google API Console project.
  • OAUTH_CLIENT_SECRET – Specify the OAuth Client Secret of the Google API Console project.
  • REDIRECT_URL – Specify the Callback URL.

Based on the OAuth API client configurations, the Google_Client class is loaded and the Google_Service_YouTube object is defined.

<?php 

// Database configuration   
define('DB_HOST''MySQL_Database_Host');
define('DB_USERNAME''MySQL_Database_Username');
define('DB_PASSWORD''MySQL_Database_Password');
define('DB_NAME''MySQL_Database_Name');

// Google API configuration
define('OAUTH_CLIENT_ID''Google_Project_Client_ID');
define('OAUTH_CLIENT_SECRET''Google_Project_Client_Secret');
define('REDIRECT_URL''https://www.example.com/youtube_video_sync.php');


// Start session
if(!session_id()) session_start();

// Include google client libraries
require_once 'google-api-php-client/autoload.php'
require_once 
'google-api-php-client/Client.php';
require_once 
'google-api-php-client/Service/YouTube.php';

// Initialize Google Client class
$client = new Google_Client();
$client->setClientId(OAUTH_CLIENT_ID);
$client->setClientSecret(OAUTH_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$client->setRedirectUri(REDIRECT_URL);

// Define an object that will be used to make all API requests
$youtube = new Google_Service_YouTube($client);

?>

Note that: The Client ID and Client Secret can be found on the API Manager page of the Google API Console project.

Database Connection (dbConfig.php)

The dbConfig.php file is used to connect and select the database using PHP and MySQL.

<?php 
// Include configuration file
require_once 'config.php';

// Create database connection
$db = new mysqli(DB_HOSTDB_USERNAMEDB_PASSWORDDB_NAME);

// Check connection
if ($db->connect_error) {
    die(
"Connection failed: " $db->connect_error);
}

Video File Upload Form (index.php)

Create an HTML form to select file and input video info (title, description, tags, privacy, etc.).

  • The enctype="multipart/form-data" attribute must be defined in the <form> tag to allow file upload.
  • On submission, the file data is posted to the server-side script (upload.php) to process the upload functionality.
<?php 
// Include configuration file
include_once 'config.php';

$status $statusMsg '';
if(!empty(
$_SESSION['status_response'])){
    
$status_response $_SESSION['status_response'];
    
$status $status_response['status'];
    
$statusMsg $status_response['status_msg'];
    
    unset(
$_SESSION['status_response']);
}
?> <!-- Status message --> <?php if(!empty($statusMsg)){ ?> <div class="alert alert-<?php echo $status?>"><?php echo $statusMsg?></div> <?php ?> <!-- Upload form --> <div class="col-md-12"> <form method="post" action="upload.php" class="form" enctype="multipart/form-data"> <div class="form-group"> <label>Video File:</label> <input type="file" name="file" class="form-control" required> </div> <div class="form-group"> <label>Title:</label> <input type="text" name="title" class="form-control" required> </div> <div class="form-group"> <label>Description:</label> <textarea name="description" class="form-control"></textarea> </div> <div class="form-group"> <label>Tags:</label> <input type="text" name="tags" class="form-control"> </div> <div class="form-group"> <label>Privacy:</label> <select name="privacy" class="form-control"> <option value="public">Public</option> <option value="private">Private</option> </select> </div> <div class="form-group"> <input type="submit" class="form-control btn-primary" name="submit" value="Upload"> </div> </form> </div>

Upload and Store Video Info in the Database (upload.php)

The upload.php file handles the file upload in PHP and the data insertion process in the MySQL database.

  • Get file data from the input field using the PHP $_FILES variable.
  • Get video info from the input field using the PHP $_POST variable.
  • Validate input to check whether mandatory fields are empty.
  • Validate file input with mime-type validation to check whether a video file (MP4, AVI, MPEG, MPG, MOV, and WMV) is selected.
  • Upload file to the local server and insert video details in the database using PHP and MySQL.
  • Store DB reference ID of the file in SESSION.
  • Create OAuth URL using createAuthUrl() method of Google_Client class.
  • Redirect user to the OAuth URL for authentication with Google account.
<?php     
// Include database configuration file
require_once 'dbConfig.php';

$statusMsg $valErr '';
$status 'danger';

// If the form is submitted
if(isset($_POST['submit'])){
    
// Allowed mime types of the file to upload
    
$allowedTypeArr = array("video/mp4""video/avi""video/mpeg""video/mpg""video/mov""video/wmv""video/rm""video/quicktime");
    
    
// Store post data in session
    
$_SESSION['postData'] = $_POST;
    
    
// Get input's value
    
$title $_POST['title'];
    
$description $_POST['description'];
    
$tags $_POST['tags'];
    
$privacy = !empty($_POST['privacy'])?$_POST['privacy']:'public';
    
    
// Validate form input fields
    
if(empty($_FILES["file"]["name"])){
        
$valErr .= 'Please select a video file to upload.<br/>';
    }elseif(!
in_array($_FILES['file']['type'], $allowedTypeArr)){
        
$valErr .= 'Sorry, only MP4, AVI, MPEG, MPG, MOV, and WMV files are allowed to upload.<br/>';
    }
        
    if(empty(
$title)){
        
$valErr .= 'Please enter the title.<br/>';
    }
    
    
// Check whether user inputs are empty
    
if(empty($valErr)){
        
$targetDir "videos/";
        
$fileName time().'_'.basename($_FILES["file"]["name"]);
        
$targetFilePath $targetDir.$fileName;
        
        
// Upload file to local server
        
if(move_uploaded_file($_FILES["file"]["tmp_name"], $targetFilePath)){
            
            
// Insert data into the database
            
$sqlQ "INSERT INTO videos (title,description,tags,privacy,file_name,created) VALUES (?,?,?,?,?,NOW())";
            
$stmt $db->prepare($sqlQ);
            
$stmt->bind_param("sssss"$db_title$db_description$db_tags$db_privacy$db_file_name);
            
$db_title $title;
            
$db_description $description;
            
$db_tags $tags;
            
$db_privacy $privacy;
            
$db_file_name $fileName;
            
$insert $stmt->execute();
            
            if(
$insert){
                
$file_id $stmt->insert_id;
                
                
// Remove post data from session
                
unset($_SESSION['postData']);
                
                
// Store DB reference ID of file in SESSION
                
$_SESSION['last_uploaded_file_id'] = $file_id;
                
                
// Get Google OAuth URL
                
$state mt_rand();
                
$client->setState($state);
                
$_SESSION['state'] = $state;
                
$googleOauthURL $client->createAuthUrl();
                
                
// Redirect user for Google authentication
                
header("Location: $googleOauthURL");
                exit();
            }else{
                
$statusMsg 'Something went wrong, please try again after some time.';
            }
        }else{
            
$statusMsg 'File upload failed, please try again after some time.';
        }
    }else{
        
$statusMsg '<p>Please fill all the mandatory fields:</p>'.trim($valErr'<br/>');
    }
}else{
    
$statusMsg 'Form submission failed!';
}

$_SESSION['status_response'] = array('status' => $status'status_msg' => $statusMsg);

header("Location: index.php");
exit();
?>

Upload Video to YouTube (youtube_video_sync.php)

This script is set as Redirect URI in Google API configuration. This means after authentication with the Google account, the user will be redirected to this script that handles the YouTube video upload process with the Google Client library using PHP.

  • Retrieve OAuth code from the query string of the URL using the PHP $_GET variable.
  • Get access token using getAccessToken() method of Google_Client class.
  • Get the video reference ID of the local database from SESSION.
  • Fetch the video info from the database based on the reference ID.
  • Retrieve the video file from the server and define other info (title, description, tags, and privacy).
  • Create a request for the YouTube Data API’s videos.insert method.
  • Read the media file and upload the video chunk by chunk to YouTube with the Google_Service_YouTube library using PHP.
  • Update YouTube video file ID in the database.
  • Redirect to the status page (status.php) where upload status will be shown.
<?php  
// Include database configuration file
require_once 'dbConfig.php';

$statusMsg '';
$status 'danger';
$redirectURL 'index.php';

// Check if an auth token exists for the required scopes
$tokenSessionKey 'token-' $client->prepareScopes();
if (isset(
$_GET['code'])) {
    if (
strval($_SESSION['state']) !== strval($_GET['state'])) {
        die(
'The session state did not match.');
    }
    
    
$client->authenticate($_GET['code']);
    
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
    
header('Location: ' REDIRECT_URL);
}

if (isset(
$_SESSION[$tokenSessionKey])) {
    
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}

// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
    
// Get file reference ID from SESSION
    
$file_id $_SESSION['last_uploaded_file_id'];
    
    if(!empty(
$file_id)){
        
// Fetch video file details from the database
        
$sqlQ "SELECT * FROM videos WHERE id = ?";
        
$stmt $db->prepare($sqlQ); 
        
$stmt->bind_param("i"$db_file_id);
        
$db_file_id $file_id;
        
$stmt->execute();
        
$result $stmt->get_result();
        
$videoData $result->fetch_assoc();
        
        if(!empty(
$videoData)){
            
$file_name $videoData['file_name'];
            
$videoPath 'videos/'.$file_name;
            
            if(!empty(
$videoData['youtube_video_id'])){
                
// Get video info from local database
                
$video_title $videoData['title'];
                
$video_desc $videoData['description'];
                
$video_tags $videoData['tags'];
                
$youtube_video_id $videoData['youtube_video_id'];
            }else{
                try {
                    
// Create a snippet with title, description, tags and category ID
                    // Create an asset resource and set its snippet metadata and type.
                    // This example sets the video's title, description, keyword tags, and
                    // video category.
                    
$snippet = new Google_Service_YouTube_VideoSnippet();
                    
$snippet->setTitle($videoData['title']);
                    
$snippet->setDescription($videoData['description']);
                    
$snippet->setTags(explode(","$videoData['tags']));
                
                    
// Numeric video category. See
                    // https://developers.google.com/youtube/v3/docs/videoCategories/list
                    
$snippet->setCategoryId("22");
                
                    
// Set the video's status to "public". Valid statuses are "public",
                    // "private" and "unlisted".
                    
$status = new Google_Service_YouTube_VideoStatus();
                    
$status->privacyStatus $videoData['privacy'];
                
                    
// Associate the snippet and status objects with a new video resource.
                    
$video = new Google_Service_YouTube_Video();
                    
$video->setSnippet($snippet);
                    
$video->setStatus($status);
                
                    
// Specify the size of each chunk of data, in bytes. Set a higher value for
                    // reliable connection as fewer chunks lead to faster uploads. Set a lower
                    // value for better recovery on less reliable connections.
                    
$chunkSizeBytes 1024 1024;
                
                    
// Setting the defer flag to true tells the client to return a request which can be called
                    // with ->execute(); instead of making the API call immediately.
                    
$client->setDefer(true);
                
                    
// Create a request for the API's videos.insert method to create and upload the video.
                    
$insertRequest $youtube->videos->insert("status,snippet"$video);
                
                    
// Create a MediaFileUpload object for resumable uploads.
                    
$media = new Google_Http_MediaFileUpload(
                        
$client,
                        
$insertRequest,
                        
'video/*',
                        
null,
                        
true,
                        
$chunkSizeBytes
                    
);
                    
$media->setFileSize(filesize($videoPath));
                
                
                    
// Read the media file and upload it chunk by chunk.
                    
$status false;
                    
$handle fopen($videoPath"rb");
                    while (!
$status && !feof($handle)) {
                        
$chunk fread($handle$chunkSizeBytes);
                        
$status $media->nextChunk($chunk);
                    }
                    
fclose($handle);
                
                    
// If you want to make other calls after the file upload, set setDefer back to false
                    
$client->setDefer(false);
                    
                    if(!empty(
$status['id'])){
                        
// Uploaded youtube video info
                        
$video_title $status['snippet']['title'];
                        
$video_desc $status['snippet']['description'];
                        
$video_tags implode(",",$status['snippet']['tags']);
                        
$youtube_video_id $status['id'];
                        
                        
// Update youtube video reference id in the database
                        
$sqlQ "UPDATE videos SET youtube_video_id=? WHERE id=?";
                        
$stmt $db->prepare($sqlQ);
                        
$stmt->bind_param("si"$db_youtube_video_id$db_file_id);
                        
$db_youtube_video_id $youtube_video_id;
                        
$db_file_id $file_id;
                        
$update $stmt->execute();
                        
                        if(
$update){
                            
// Delete video file from local server
                            
@unlink($videoPath);
                        }
                        
                        unset(
$_SESSION['last_uploaded_file_id']);
                        
                        
$status 'success';
                        
$statusMsg 'Video has been uploaded to YouTube successfully!';
                    }
                } catch (
Google_Service_Exception $e) {
                    
$statusMsg 'A service error occurred: <code>'.$e->getMessage().'</code>';
                } catch (
Google_Exception $e) {
                    
$statusMsg 'An client error occurred: <code>'.$e->getMessage().'</code>';
                    
$statusMsg .= '<br/>Please reset session <a href="logout.php">Logout</a>';
                }
            }
            
            if(!empty(
$youtube_video_id)){
                
$redirectURL 'status.php?fid='.base64_encode($file_id);
            }
        }else{
            
$statusMsg 'File data not found!';
        }
    }else{
        
$statusMsg 'File reference not found!';
    }
    
    
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
}else{
    
$statusMsg 'Failed to fetch access token!';
}

$_SESSION['status_response'] = array('status' => $status'status_msg' => $statusMsg);

header("Location: $redirectURL");
exit();

Note that: This file URL must be set as Redirect URL in Authorized redirect URIs section of the Google API console project.

YouTube Upload Status (status.php)

Once the YouTube video upload process is completed, the user is redirected to this status page. In this status.php file, the uploaded video details are displayed on the webpage.

  • The video information is fetched from the database based on the DB reference ID passed in the URL.
  • Embed YouTube video URL on webpage using <embed> tag.
  • Display the video details with the YouTube video view link.
<?php 
// Include configuration file
include_once 'dbConfig.php';

if(!empty(
$_GET['fid'])){
    
$file_id base64_decode($_GET['fid']);
    
    
// Fetch video details from the database
    
$sqlQ "SELECT * FROM videos WHERE id = ?";
    
$stmt $db->prepare($sqlQ); 
    
$stmt->bind_param("i"$db_file_id);
    
$db_file_id $file_id;
    
$stmt->execute();
    
$result $stmt->get_result();
    
$videoData $result->fetch_assoc();
}

if(empty(
$videoData)){
    
header("Location: index.php");
    exit();
}

$status $statusMsg '';
if(!empty(
$_SESSION['status_response'])){
    
$status_response $_SESSION['status_response'];
    
$status $status_response['status'];
    
$statusMsg $status_response['status_msg'];
    
    unset(
$_SESSION['status_response']);
}
?> <h2>Video Details <a href="logout.php"><span class="badge bg-primary">logout</span></a></h2> <!-- Status message --> <?php if(!empty($statusMsg)){ ?> <div class="alert alert-<?php echo $status?>"><?php echo $statusMsg?></div> <?php ?> <!-- YouTube video info --> <?php
if(!empty($videoData)){
    
$youtubeURL 'https://youtu.be/'.$videoData['youtube_video_id'];
    
$privacy_class = ($videoData['privacy'] == 'private')?'danger':'success';
?> <div class="card"> <embed width="100%" src="https://www.youtube.com/embed/<?php echo $videoData['youtube_video_id']; ?>"></embed> <div class="card-body"> <h5 class="card-title"><?php echo $videoData['title']; ?></h5> <p class="card-text"><?php echo $videoData['description']; ?></p> <p><b>Tags:</b> <?php echo $videoData['tags']; ?></p> <p><b>Privacy:</b> <span class="badge bg-<?php echo $privacy_class?>"><?php echo $videoData['privacy']; ?></span></p> <p><b>YouTube URL:</b> <a href="<?php echo $youtubeURL?>" target="_blank"><?php echo $youtubeURL?></a></p> </div> <a href="index.php" class="btn btn-primary">New Upload</a> </div> <?php ?>

Logout (logout.php)

On first time authentication, a SESSION is generated and the user doesn’t need to authenticate again for upload. If the user wishes to log out from the Google OAuth, the logout.php file is loaded.

  • Revoke token and destroy the SESSION data.
  • Redirect the user to the homepage.
<?php 
// Include configuration file
require_once 'config.php';

// Revoke token & destroy session
$client->revokeToken();
session_destroy();

// Redirect to the homepage
header("Location: index.php");
exit;
?>

Get Videos from YouTube Channel using Data API v3 and PHP

Conclusion

YouTube Data API provides the easiest way to upload video to YouTube channel with PHP. You can upload videos from the website to YouTube channel using PHP. In this example script, the Google client library is used to upload video to YouTube with YouTube Data API using PHP.

Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request

28 Comments

  1. Simi Said...
  2. Tegatti Said...
  3. James Eco Said...
  4. Ammara Said...
    • CodexWorld Said...
  5. Ali Said...
  6. Prtam Said...
  7. Rahul Said...
  8. Kufre Said...
  9. Darshan Kini Said...
  10. Pritam Saha Said...
    • CodexWorld Said...
  11. Sachin Sharma Said...
  12. Ken Said...
  13. Jos Said...
    • CodexWorld Said...
  14. Hitesh Said...
  15. Cingcow Said...
  16. Arpit Kumar Pal Said...
  17. Rajdeep Singh Said...
  18. Developer Said...
  19. Adnane Said...
  20. User Said...
  21. Ahmed Said...
  22. Lalit Said...
  23. Randhir Said...
  24. Michoul Said...
  25. Developer Said...

Leave a reply

keyboard_double_arrow_up