使用curl和api v3在Youtube上上传视频

时间:2012-11-07 16:41:23

标签: php curl upload youtube-api

我会在PHP中使用带有curl的Youtube API v3上传视频,如下所述:https://developers.google.com/youtube/v3/docs/videos/insert

我有这个功能

function uploadVideo($file, $title, $description, $tags, $categoryId, $privacy)
{
    $token = getToken(); // Tested function to retrieve the correct AuthToken

    $video->snippet['title']         = $title;
    $video->snippet['description']   = $description;
    $video->snippet['categoryId']    = $categoryId;
    $video->snippet['tags']          = $tags; // array
    $video->snippet['privacyStatus'] = $privacy;
    $res = json_encode($video);

    $parms = array(
        'part'  => 'snippet',
        'file'  => '@'.$_SERVER['DOCUMENT_ROOT'].'/complete/path/to/'.$file
        'video' => $res
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://www.googleapis.com/upload/youtube/v3/videos');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $parms);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$token['access_token']));
    $return = json_decode(curl_exec($ch));
    curl_close($ch);

    return $return;
}

但它会返回

stdClass Object
(
    [error] => stdClass Object
        (
            [errors] => Array
                (
                    [0] => stdClass Object
                        (
                            [domain] => global
                            [reason] => badContent
                            [message] => Unsupported content with type: application/octet-stream
                        )

                )

            [code] => 400
            [message] => Unsupported content with type: application/octet-stream
        )

)

该文件是MP4。

任何人都可以提供帮助吗?

4 个答案:

答案 0 :(得分:20)

更新版本:现在使用自定义上传网址并通过上传过程发送元数据。整个过程需要2个请求:

  1. 获取自定义上传位置

    首先,对上传网址发出POST请求:

    "https://www.googleapis.com/upload/youtube/v3/videos"
    

    您需要发送2个标题:

    "Authorization": "Bearer {YOUR_ACCESS_TOKEN}"
    "Content-type": "application/json"
    

    您需要发送3个参数:

    "uploadType": "resumable"
    "part": "snippet, status"
    "key": {YOUR_API_KEY}
    

    您需要在请求正文中发送视频的元数据:

        {
            "snippet": {
                "title": {VIDEO TITLE},
                "description": {VIDEO DESCRIPTION},
                "tags": [{TAGS LIST}],
                "categoryId": {YOUTUBE CATEGORY ID}
            },
            "status": {
                "privacyStatus": {"public", "unlisted" OR "private"}
            }
        }
    

    根据此请求,您应该在标题中获得一个“位置”字段的回复。

  2. POST到自定义位置以发送文件。

    对于上传,您需要1个标题:

    "Authorization": "Bearer {YOUR_ACCESS_TOKEN}"
    

    并将文件作为您的数据/正文发送。

  3. 如果您了解其客户端的工作原理,您会看到他们建议您在返回错误代码500,502,503或504时重试。显然,您需要在重试和最多重试次数之间等待一段时间。虽然我使用python& urllib2而不是cURL。

    此外,由于自定义上传位置,此版本具有上载可恢复功能,但我尚未需要。

答案 1 :(得分:1)

很遗憾,我们还没有提供PHP上传的YouTube API v3的具体示例,但我的一般建议是:

  • 使用PHP client library代替cURL。
  • 将您的代码基于为Drive API编写的this example。由于YouTube API v3与其他Google API共享通用API基础结构,因此上传文件等内容的示例应该在不同服务之间非常相似。
  • 请查看Python example,了解需要在YouTube v3上传中设置的特定元数据。

一般来说,你的cURL代码有很多不正确之处,我无法完成修复它所需的所有步骤,因为我认为使用PHP客户端库是一个更好的选择。如果您确信要使用cURL,那么我会推荐其他人提供具体的指导。

答案 2 :(得分:0)

一个python脚本:

# categoryId is '1' for Film & Animation
# to fetch all categories: https://www.googleapis.com/youtube/v3/videoCategories?part=snippet&regionCode={2 chars region code}&key={app key}
meta =  {'snippet': {'categoryId': '1',
  'description': description,
  'tags': ['any tag'],
  'title': your_title},
  'status': {'privacyStatus': 'private' if private else 'public'}}

param = {'key': {GOOGLE_API_KEY},
         'part': 'snippet,status',
         'uploadType': 'resumable'}

headers =  {'Authorization': 'Bearer {}'.format(token),
           'Content-type': 'application/json'}

#get location url
retries = 0
retries_count = 1
while retries <= retries_count: 
    requset = requests.request('POST', 'https://www.googleapis.com/upload/youtube/v3/videos',headers=headers,params=param,data=json.dumps(meta))
    if requset.status_code in [500,503]:
        retries += 1
    break

if requset.status_code != 200:
    #do something

location = requset.headers['location']

file_data = open(file_name, 'rb').read()

headers =  {'Authorization': 'Bearer {}'.format(token)}

#upload your video
retries = 0
retries_count = 1
while retries <= retries_count:
    requset = requests.request('POST', location,headers=headers,data=file_data)
    if requset.status_code in [500,503]:
        retries += 1
    break

if requset.status_code != 200:
    #do something

# get youtube id
cont = json.loads(requset.content)            
youtube_id = cont['id']

答案 3 :(得分:0)

我可以使用以下shell脚本将视频上传到YouTube上的频道。

#!/bin/sh

# Upload the given video file to your YouTube channel.

cid_base_url="apps.googleusercontent.com"
client_id="<YOUR_CLIENT_ID>.$cid_base_url"
client_secret="<YOUR_CLIENT_SECRET>"
refresh_token="<YOUR_REFRESH_TOKEN>"
token_url="https://accounts.google.com/o/oauth2/token"
api_base_url="https://www.googleapis.com/upload/youtube/v3"
api_url="$api_base_url/videos?uploadType=resumable&part=snippet"

access_token=$(curl -H "Content-Type: application/x-www-form-urlencoded" -d refresh_token="$refresh_token" -d client_id="$client_id" -d client_secret="$client_secret" -d grant_type="refresh_token" $token_url|awk -F '"' '/access/{print $4}')

auth_header="Authorization: Bearer $access_token"
upload_url=$(curl -I -X POST -H "$auth_header" "$api_url"|awk -F ' |\r'  '/loc/{print $2}'); curl -v -X POST --data-binary "@$1" -H "$auth_header" "$upload_url"

有关如何获取自定义变量值,请参阅this类似问题。