使用swift和alamofire将视频(和属性)上传到youtube



我有兴趣将视频以及标题,描述和关键字上传到youtube。 下面的代码将视频上传到YouTube,没有任何属性:

func postVideoToYouTube(token: String, callback: Bool -> Void){
let headers = ["Authorization": "Bearer (token)"]
let urlYoutube = "https://www.googleapis.com/upload/youtube/v3/videos?part=id"
let path = NSBundle.mainBundle().pathForResource("video", ofType: "mp4")
let videodata: NSData = NSData.dataWithContentsOfMappedFile(path!)! as! NSData
upload(
    .POST,
    urlYoutube,
    headers: headers,
    multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(data: videodata, name: "video", fileName: "video.mp4", mimeType: "application/octet-stream")
    },
    encodingCompletion: { encodingResult in
        switch encodingResult {
        case .Success(let upload, _, _):
            upload.responseJSON { request, response, error in
                print(response)
                callback(true)
            }
        case .Failure(_):
            callback(false)
        }
    })

}

我一直在尝试修改urlYoutube以包含必要的片段信息,但无济于事:

let snippetTitle = "The Best Video Ever"
let snippetDesc = "first video upload with title"
let snippetTags = "best,video,ever,snoopy,monkey,charlie"
let urlYoutube = "https://www.googleapis.com/upload/youtube/v3/videos?part=id&snippet.title=%@&snippet.description=%@&snippet.keywords=%@", snippetTitle, snippetDesc, snippetTags)"

我尝试的另一种方法(感谢@adjuremods建议)是使用基于 Youtube-API 的请求正文来编辑以前上传的视频。 因此,首先,我定义了一个视频资源:

let parms = [
  "kind": "youtube#video",
  "id" : returnedId,
  "snippet.title" : "summer vacation cali",
  "snippet.description" : "had fun in the sun",
  "snippet.tags" : ["surf","fun","sun"],
  "snippet.categoryId" : "1"
]

并将其作为 PUT 请求发送,如下所示:

do {
  let parmsJson = try NSJSONSerialization.dataWithJSONObject(parameters, options: .PrettyPrinted)
  let putURL = NSURL(string: "https://www.googleapis.com/upload/youtube/v3/videos")!
  let request = NSMutableURLRequest(URL: putURL)
  request.HTTPMethod = "PUT"
  request.setValue("Bearer (token)", forHTTPHeaderField: "Authorization")
  request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
  request.HTTPBody = parmsJson
  let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
    if error != nil{
      print("Error -> (error)")
      return
    }
    do {
      let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
      print("Result -> (result)")
    } catch {
      print("Error -> (error)")
    }
  }
  task.resume()
  //return task

} catch {
  print ("...could not accomplish put request")
}   

不幸的是,无论我如何修改视频资源,我得到的结果总是相同的:

Result -> Optional(["error": {
code = 400;
errors =     (
            {
        domain = global;
        message = "Unsupported content with type: application/json; charset=UTF-8";
        reason = badContent;
    }
);
message = "Unsupported content with type: application/json; charset=UTF-8";

有人可以建议我可能出错的地方吗? 我对如何设置 API 定义的这些参数没有非常清楚的了解:

https://developers.google.com/youtube/v3/docs/videos/insert#parameters

在 multipartFormData 块中添加一行参数值,如下所示(将代码放在视频项之前 - 和 - 为每个隐含结构添加任何其他代码段属性值):

multipartFormData.appendBodyPart(data:"{'snippet':{'title' : 'TITLE_TEXT', 'description': 'DESCRIPTION_TEXT'}}".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"snippet", mimeType: "application/json")

帖子网址也应更改为部分=片段

https://www.googleapis.com/upload/youtube/v3/videos?part=snippet

 .POST,
    "https://www.googleapis.com/upload/youtube/v3/videos?part=snippet",
    headers: headers,
    multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(data:"{'snippet':{'title' : 'TITLE_TEXT', 'description': 'DESCRIPTION_TEXT'}}".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"snippet", mimeType: "application/json")
        multipartFormData.appendBodyPart(data: videodata, name: "video", fileName: "video.mp4", mimeType: "application/octet-stream")
},

设置标题、描述、标记等将需要您使用基于 API 的请求正文。查看此处提出的此问题,了解如何在 Swift 中设置请求正文。

let json = [ "title":"ABC" , "dict": mapDict ]
let jsonData = NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted, error: nil)
// insert json data to the request
request.HTTPBody = jsonData

请记住,请求正文应该是视频的资源表示形式

哦,

天哪....事实证明,这是一个相当大的难题。 从之前的 youtube 答案中,有人暗示上传带有片段元数据的视频的唯一方法是通过 POST 和 PUT 请求的组合......然而,让这些工作是一个相当大的挑战。 一路上我学到的一件非常有用的事情是,Alamofire 在发出可用于对 cURL 会话进行故障排除的请求时会返回一个对象:

let putRequest = request(.PUT, "https://www.googleapis.com/youtube/v3/videos?part=snippet&key=(ios_key)", parameters: dictionaryParameters, encoding: .JSON , headers: headers)
          debugPrint(putRequest)

这将返回如下输出:

$ curl -i 
-X PUT 
-H "Authorization: Bearer ##########################" 
-H "Content-Type: application/json" 
-H "Accept-Language: en-US;q=1.0" 
-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" 
-H "User-Agent: testVideoApp/com.thinkforward.testVideoApp (1; OS Version 9.2 (Build 13C75))" 
-d "{"id":"###########","snippet":{"title":"something in the way","tags":["whisky","tango","fox"],"description":"is this finally gonna work?"}}" 

啊哈! 现在我们有一个cURL命令,我们可以独立于Alamofire进行测试。 一旦我让它工作,剩下的就是对命令进行逆向工程,以确保我将正确的参数传递给 Alamofire......这就是我发现 Alamofire 希望以非常特定的方式传递参数的方式:

 parameters: <[String : AnyObject]?>

有了这个情报,我重建了我的词典,如下所示:

let dictionarySnippet :Dictionary<String, AnyObject>  = [
  "title" : "something in the way",
  "description" : "is this finally gonna work?",
  "tags" : ["whisky","tango","fox"],
  "categoryId" : "1"
]
let dictionaryParameters :Dictionary<String, AnyObject> = [
            "id" : "(returnedId)",
            "snippet" : dictionarySnippet,
          ]

接下来,我发现发出PUT请求实际上需要与我用于POST的范围不同的范围。 由于我需要发出这两种类型的请求,因此我必须更新我的范围变量,如下所示:

let scope = "https://www.googleapis.com/auth/youtube+https://www.googleapis.com/auth/youtube.upload"

同样,POST 和 PUT 请求需要单独的 URL:

https://www.googleapis.com/upload/youtube/v3/videos?part=snippet for POST
https://www.googleapis.com/youtube/v3/videos?part=snippet&key=(ios_key) for PUT

有了这些更改,我的问题中发布的代码就像一个魅力。 它不是很优雅,但它可以完成工作。

相关内容

  • 没有找到相关文章

最新更新