Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube API video upload error: parseError /w python

The example code for Google's YouTube Data API is a piece of junk. It's so complicated and tied to the oauth redirect flow that I can't use it. Trying to go raw with requests pip and not getting too far.

I've followed the instructions exactly (as far as I can tell), with the following code:

import json
import os
import sys
import urllib

import requests

payload_file = None
payload = None

print 'Loading Config'

# Get the directory path of this file.  When using any relative file paths make
# sure they are relative to current_dir so that the script can be run from any CWD.
current_dir = os.path.dirname(os.path.abspath(__file__))

# Reads in the config.json file then parses it
config = json.loads(open(os.path.join(current_dir, '..', 'config.json')).read())

print 'Parsing Payload'

for i in range(len(sys.argv)):

    if sys.argv[i] == "--json" and (i + 1) < len(sys.argv):
        payload = json.loads(sys.argv[i + 1])

    elif sys.argv[i] == "-payload" and (i + 1) < len(sys.argv):
        payload_file = sys.argv[i + 1]
        with open(payload_file,'r') as f:
            payload = json.loads(f.read())
        break


print 'Configuring youtube with token {0}'.format(payload['token'])



print 'Downloading video...'

# See how big it is
f = urllib.urlopen(payload['url'])
content_length = int(f.headers["Content-Length"])

# Download it
# urllib.urlretrieve(payload['url'], "video.mp4")

metadata = {
    'snippet' : {
        'title': payload['title'],
        "categoryId": 22
    },
    'status' : {
        "privacyStatus": "public",
        "embeddable": True,
        "license": "youtube"
    }
}

if 'tags' in payload:
    metadata['snippet']['tags'] = payload['tags']

if 'description' in payload:
    metadata['snippet']['description'] = payload['description']


headers = {
    'Authorization' : 'Bearer {0}'.format(payload['token']),
    'Content-Type' : 'application/json; charset=UTF-8',
    'Content-Length' : json.dumps(metadata).__len__(),
    'X-Upload-Content-Length' : content_length,
    'X-Upload-Content-Type' : 'video/*',
}

print 'Attempting to upload video'

print headers

# upload video file
r = requests.post('https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status', data=metadata, headers=headers);

print "RESPONSE!"
print r.text

# files = {
#     'file': video_file,
# }
# r = requests.post('https://www.googleapis.com/upload/youtube/v3/videos', data={ "video" : video }, headers=headers);

Obviously its not finished, but its dying on the metadata upload request with the following output:

Loading Config
Parsing Payload
Configuring youtube with token <access-token>
Downloading video...
Attempting to upload video
{'X-Upload-Content-Length': 51998563, 'Content-Length': 578, 'Content-Type': 'application/json; charset=UTF-8', 'X-Upload-Content-Type': 'video/*', 'Authorization': 'Bearer <access-token>'}
RESPONSE!
{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "parseError",
    "message": "Parse Error"
   }
  ],
  "code": 400,
  "message": "Parse Error"
 }
}

This error is not even listed in their "Errors" docs.

What is wrong with my code?

like image 366
Phil Sturgeon Avatar asked Nov 01 '22 13:11

Phil Sturgeon


1 Answers

Here is an example in python that works. It assumes you've already done the oauth part though.

import requests
from os import fstat
import json

fi = open('myvideo.mp4')

base_headers = {
    'Authorization': '%s %s' % (auth_data['token_type'],
                                auth_data['access_token']),
    'content-type': 'application/json'
}

initial_headers = base_headers.copy()
initial_headers.update({
    'x-upload-content-length': fstat(fi.fileno()).st_size,
    'x-upload-content-type': 'video/mp4'
})
initial_resp = requests.post(
    'https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails',
    headers=initial_headers,
    data=json.dumps({
        'snippet': {
            'title': 'my title',
        },
        'status': {
            'privacyStatus': 'unlisted',
            'embeddable': True
        }
    })
)
upload_url = initial_resp.headers['location']
resp = requests.put(
    upload_url,
    headers=base_headers,
    data=fi
)
fi.close()
like image 154
vangheem Avatar answered Nov 15 '22 06:11

vangheem