我还没有找到关于SO的相关和最新答案。
以下是我目前正在使用的代码,所有请求都已正确处理但未发布视频?
if let userID = Twitter.sharedInstance().sessionStore.session()?.userID {
var client = TWTRAPIClient(userID: userID)
let text: String = "Testing Video"
let videoLength: String = "\(self.video.length)"
print(videoLength)
var initError: NSError?
var message = ["status": text, "command" : "INIT", "media_type" : "video/m4v", "total_bytes" : videoLength]
let preparedRequest: NSURLRequest = client.URLRequestWithMethod("POST", URL: self.strUploadUrl, parameters: message, error: &initError)
client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
if error == nil {
do {
let json: NSDictionary = try (NSJSONSerialization.JSONObjectWithData(responseData!, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary)!
print("JSON is \(json)")
let mediaID = json.objectForKey("media_id_string") as! String
client = TWTRAPIClient(userID: userID)
var uploadError: NSError?
let videoString = self.video.base64EncodedStringWithOptions([])
message = ["command" : "APPEND", "media_id" : mediaID, "segment_index" : "0", "media" : videoString]
let preparedRequest = client.URLRequestWithMethod("POST", URL: self.strUploadUrl, parameters: message, error: &uploadError)
client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
if error == nil {
client = TWTRAPIClient(userID: userID)
var finalizeError: NSError?
message = ["command":"FINALIZE", "media_id": mediaID]
let preparedRequest = client.URLRequestWithMethod("POST", URL: self.strUploadUrl, parameters: message, error: &finalizeError)
client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
if error == nil {
client = TWTRAPIClient(userID: userID)
var sendError: NSError?
let message = ["status": text, "wrap_links": "true", "media_ids": mediaID]
//var updateMessage = NSMutableDictionary(dictionary: message)
let preparedRequest = client.URLRequestWithMethod("POST", URL: self.strStatusUrl, parameters: message , error: &sendError)
client.sendTwitterRequest(preparedRequest, completion: { (urlResponse: NSURLResponse?, responseData: NSData?, error: NSError?) -> Void in
})
} else {
print("Command FINALIZE failed \n \(error!)")
}
})
} else {
print("Command APPEND failed")
}
})
}
catch {
print("\(error)")
}
}
else {
print("\(error.debugDescription)Command INIT failed")
}
})
}
上述所有代码均有效,但视频未上传。我无法弄清楚我错过了什么,Twitter的文档在发布视频时非常糟糕。
答案 0 :(得分:3)
如果您想将@ Trung的代码转换为Swift 4,并且如果您想使用TwitterKit,则可以使用此枚举来处理所有上传阶段:
enum UploadStage {
case initial(size: String, videoDuration: Int?) // if your video duration is <= 30s, you can pass nil here
case append(mediaId: String, videoData: Data, segment: Int)
case finalize(mediaId: String)
case status(status: String, mediaId: String)
static let videoChunkMaxSize = 5 * 1000 * 1000
var parameters: [String: Any] {
get {
switch self {
case .initial(let size, let videoDuration):
var params = ["command":stageName, "total_bytes": size, "media_type": "video/mp4"]
if let videoDuration = videoDuration, videoDuration > 30 {
params["media_category"] = "tweet_video"
}
return params
case .append(let mediaId, _ , let segment):
let videoChunkString = self.videoChunk!.base64EncodedString(options: [])
return ["command":stageName, "media_id": mediaId, "segment_index": "\(segment)", "media": videoChunkString]
case .finalize(let mediaId):
return ["command":stageName, "media_id": mediaId]
case .status(let status, let mediaId):
return ["status": status, "wrap_links": "true", "media_ids": mediaId]
}
}
}
var stageName: String {
get {
switch self {
case .initial:
return "INIT"
case .append:
return "APPEND"
case .finalize:
return "FINALIZE"
case .status:
return "STATUS"
}
}
}
var videoChunk: Data? {
switch self {
case .append(_ , let videoData, let segment):
if videoData.count > UploadStage.videoChunkMaxSize {
let maxPos = segment * UploadStage.videoChunkMaxSize + UploadStage.videoChunkMaxSize
let range: Range<Data.Index> = segment * UploadStage.videoChunkMaxSize..<(maxPos >= videoData.count ? videoData.count : maxPos)
return videoData.subdata(in: range)
}
return videoData
default:
return nil
}
}
var urlString: String {
switch self {
case .initial, .append, .finalize:
return "https://upload.twitter.com/1.1/media/upload.json"
case .status:
return "https://api.twitter.com/1.1/statuses/update.json"
}
}
}
通过传递下一阶段枚举值,可以在具有递归调用的方法中使用UploadStage枚举:
func uploadTwitterVideo(videoData: Data, status: String, stage: UploadStage, success: @escaping () -> Void, failure: @escaping (Error?) -> Void) {
let client = TWTRAPIClient.withCurrentUser()
var clientError: NSError?
let urlRequest = client.urlRequest(withMethod: "POST", urlString: stage.urlString, parameters: stage.parameters, error: &clientError)
if clientError == nil {
client.sendTwitterRequest(urlRequest) { (urlResponse, responseData, connectionError) in
guard connectionError == nil else {
print("There was an error: \(connectionError!.localizedDescription)")
failure(connectionError)
return
}
self.handleError(urlResponse, failure: failure)
if let data = responseData, let dataString = String(data: data, encoding: .utf8), let urlResponse = urlResponse {
print("Twitter stage \(stage.stageName) URL response : \(urlResponse), response data: \(dataString)")
var nextStage: UploadStage?
do {
switch stage {
case .initial:
let returnedJSON = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String:Any]
if let mediaId = returnedJSON["media_id_string"] as? String {
print("stage one success, mediaID -> \(mediaId)")
nextStage = .append(mediaId: mediaId, videoData:videoData, segment: 0)
}
case .append(let mediaId, let videoData, let segment):
if ((segment + 1) * UploadStage.videoChunkMaxSize < videoData.count) {
nextStage = .append(mediaId: mediaId, videoData: videoData, segment: segment + 1)
} else {
nextStage = .finalize(mediaId: mediaId)
}
case .finalize(let mediaId):
nextStage = .status(status: status, mediaId: mediaId)
case .status:
success()
}
if let nextStage = nextStage {
self.uploadTwitterVideo(videoData: data, status: status, stage: nextStage, success: success, failure: failure)
}
} catch let error as NSError {
failure(error)
}
}
}
}
}
答案 1 :(得分:2)
我很同情你关于Twitter糟糕的文档。 找出你得到的错误。
以下是我希望它有用的实施说明:
查看我的项目https://github.com/mtrung/TwitterVideoUpload。我知道它在Obj-C中但它有效。