2016-03-27 13 views
2

私はSOに関連した最新の回答が見つかりませんでした。iOS Swift:TwitterKitでTwitterにビデオを投稿するには?

ここに私が現在使用しているコードはありますが、すべてのリクエストは正しく処理されますが、ビデオは掲載されていませんか?

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の文書は非常に貧弱です。

答えて

2

私はTwitterの貧弱なドキュメントについてあなたに同情します。 エラーの内容を確認してください。

  1. Twitterのビデオ要件: https://dev.twitter.com/rest/public/uploading-media#videorecsを以下

    は、私はそれが役に立てば幸い実装のメモです。

  2. FINALIZEコマンドは、アップロードを完了する前にTwitterビデオ要件ごとのビデオファイル を確認します。
  3. 「無効またはサポートされていないメディア、理由:UnsupportedMedia」の応答データを含む「HTTPステータス400不良要求」が表示された場合FINALIZEコマンドを送信した後にエラーが発生した場合、Twitterビデオ要件でビデオファイルを確認する必要があります。

私のプロジェクトhttps://github.com/mtrung/TwitterVideoUploadをチェックしてください。私はそれがObj-Cにあることを知っていますが、うまくいきます。

1

あなたはスウィフト4にチュンのコード@に変換したい、とあなたはTwitterKitを使用する場合は、すべてのアップロードの段階を処理するために、この列挙型を使用することができた場合:UploadStage列挙型は、法で使用することができ

enum UploadStage { 
    case initial(size: String) 
    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): 
       return ["command":stageName, "total_bytes": size, "media_type": "video/mp4"] 
      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 url: URL { 
     switch self { 
     case .initial, .append, .finalize: 
      return URL(string: "https://upload.twitter.com/1.1/media/upload.json")! 
     case .status: 
      return URL(string: "https://api.twitter.com/1.1/statuses/update.json")! 
     } 
    } 
} 

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 

      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)") 

       guard connectionError == nil else { 
        print("There was an error: \(connectionError!.localizedDescription)") 
        failure(connectionError) 
        return 
       } 

       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) 
       } 
      } 
     } 
    } 
} 
+0

これは優れた実装であり、初めて試したときにうまく機能しました。一つのことは、レスポンスデータのif-letからあなたのconnectionErrorガードを引き出す必要があるということです。長い動画ではエラーが返ってきましたが、応答データはありませんでした。そのエラーをチェックアウトするまでエラーは表示されませんでした。 Twitterのドキュメントでは、同期のアップロードでは最大動画の長さは30、非同期の場合は140秒ですが、この非同期メソッドを使用して30秒を超える動画をアップロードすると、400エラー(TWTRComposerViewControllerが発生するエラーと同じエラー)が発生します。その140秒の制限に達する方法に関するアイデア? –

+0

見つかった: "制約はmedia_categoryパラメータに基づいて変化するかもしれない"と言われていますが、それ以上のガイダンスは難しいです。基本的には、30秒を超える動画の場合は、「media_category」:「tweet_video」をINITパラメータに追加してから、ファイナライズステージの後に、ビデオが持つ応答を得るまで、最後のステージのリクエストを繰り返す必要があります完成した処理。準備が整っていなければ、応答はなく、400エラーが発生します。その後、最終段階に進むことでツイートを完成させることができます。 https://www.jwz.org/blog/2016/06/twitters-musical-chairs-video-specifications/#comment-167386 –

関連する問題