代码之家  ›  专栏  ›  技术社区  ›  Abhirajsinh Thakore

Swift-将视频上载到Twitter时,请求状态为400

  •  0
  • Abhirajsinh Thakore  · 技术社区  · 7 年前

    我正在尝试使用我的设备将视频上传(即共享)到twitter。到目前为止,我已经使用了下面的代码来实现这一点。

         // video Upload
    
        func requestAccessToTwitterAccount(videoURL:NSURL,fileSize:UInt32){
    
            let accountStore = ACAccountStore()
            let twitterAccountType = accountStore.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)
            accountStore.requestAccessToAccounts(with: twitterAccountType, options: nil) { (granted, error) in
    
                if granted {
                    let accounts = accountStore.accounts(with: twitterAccountType)
                    if (accounts?.count)! > 0 {
                        self.twitterAccount = accounts?.last as! ACAccount
                        self.uploadVideoToTwitter(videoURL: videoURL, fileSize: fileSize)
                    }
                else{
                        let error = "Please set your twitter account in Settings."
                        print(error)
                    }
                }
            else {
                print("App permissions are disabled in device twitter settings, please enable it.")
            }
        }
    }
        func uploadVideoToTwitter(videoURL:NSURL,fileSize: UInt32){
            print(videoURL.path!)
            if let videoData = NSData(contentsOfFile: videoURL.path!){
    
                self.tweetVideoInit(videoData: videoData, videoSize: Int(fileSize))
            }else{
                print("Something Wrong")
            }
        }
    
        func tweetVideoInit(videoData:NSData,videoSize:Int) {
    
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
    
            var params = [String:String]()
    
            params["command"] = "INIT"
            params["total_bytes"]  = String(videoData.length)
            params["media_type"]  = "video/MOV"
    
            print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(error!)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
    
                            if let tweetID = dictionary["media_id_string"] as? String{
                                self.tweetVideoApped(videoData: videoData, videoSize: videoSize, mediaId: tweetID, chunk: 0)
                            }
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    
    
    
        func tweetVideoApped(videoData:NSData,videoSize:Int ,mediaId:String,chunk:NSInteger) {
    
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
    
            var params = [String:String]()
    
            params["command"] = "APPEND"
            params["media_id"]  = mediaId
            params["segment_index"]  = String(chunk)
    
            print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
            postRequest?.addMultipartData(videoData as Data!, withName: "media", type: "video/mov", filename:"mediaFile")
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(err)
    
                }else{
                    self.tweetVideoFinalize(mediaId: mediaId)
                }
            })
        }
    
        func tweetVideoFinalize(mediaId:String) {
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
    
            var params = [String:String]()
            params["command"] = "FINALIZE"
            params["media_id"]  = mediaId
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            self.postStatus(mediaId: mediaId)
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    
        func postStatus(mediaId:String) {
    
            let uploadURL = NSURL(string:"https://api.twitter.com/1.1/statuses/update.json")
    
            var params = [String:String]()
            //params["status"] = twitterDescription
            params["media_ids"]  = mediaId
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
    
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            print("video uploaded")
                            let alert = UIAlertController(title: "Success", message: "video uploaded successfully.", preferredStyle: UIAlertControllerStyle.alert)
                            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
                            self.present(alert, animated: true, completion: nil)
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    

    现在的问题是这样的,我不确定问题出在哪里,但当我尝试上传一段视频时 10 secs 已上载 成功地 ,但当我尝试视频超过10秒时,会出现错误 请求状态400 视频不上传。

    注:- 我的视频格式是 .MOV 大小差不多 6.4MB 所以我想根据 Twitter 用于视频上传。

    仅供参考:- 我也提到了这个链接- Twitter Upload Demo

    还有 Official Documentation 建议以下限制 我不超过。

    enter image description here

    有人能帮我解释一下为什么会发生这个问题吗。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Jatin Vashisht    7 年前

    这是我之前使用的代码,对我来说效果很好。试试这个

    let account = ACAccountStore()
                let accountType = account.accountType(
                    withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)
    
                account.requestAccessToAccounts(with: accountType, options: nil,
                                                completion: {(success, error) in
    
                                                    if success {
                                                        let arrayOfAccounts =
                                                            account.accounts(with: accountType)
    
                                                        if (arrayOfAccounts?.count)! > 0 {
                                                            let twitterAccount = arrayOfAccounts?.last as! ACAccount
                                                            let message = “your text here”
                                                            print(twitterAccount)
    
    
                                                            self.socialVideo.uploadTwitterVideo(self.coachController?.videoData as Data!, comment: message, account: twitterAccount, withCompletion: { (success, value) in
    
    
                                                                if success == true {
    
                                                                    self.showToast(message: "Uploaded Succesfully")
                                                                }
    
                                                            })
                                                        }
                                                    }
                })
    

    链接下载SocialVideo Helper-> https://github.com/liu044100/SocialVideoHelper

        2
  •  0
  •   Abhirajsinh Thakore    7 年前

    在研究 Docs 没有找到任何方法。对我有用的东西是 Compressing 视频。

    我使用以下代码压缩视频并将其转换为 .m4v 格式以及它对我的作用。

    注:- 上载视频的限制为 15MB 30秒 最大值

    将视频上载到的完整代码 Twitter 是:

    func imagePickerController(_ picker: UIImagePickerController,
                               didFinishPickingMediaWithInfo info: [String : Any])
    {
        if  let video = info[UIImagePickerControllerMediaURL] as? URL{
            let asset = AVURLAsset(url: video)
            let durationInSeconds = asset.duration.seconds
            print(durationInSeconds)
    
            if durationInSeconds < 30{
                arrImageURL.removeAll()
                btnSelectImage.setBackgroundImage(nil, for: .normal)
                btnSelectImage.setTitle("Select Image to attach", for: .normal)
                videoURL = video
                print(videoURL)
                let innerVideoURL = video
                let data = NSData(contentsOf: innerVideoURL as URL)!
                print("File size before compression: \(Double(data.length / 1048576)) mb")
                let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".m4v")
                compressVideo(inputURL: innerVideoURL , outputURL: compressedURL) { (exportSession) in
                    guard let session = exportSession else {
                        return
                    }
    
                    switch session.status {
                    case .unknown:
                        break
                    case .waiting:
                        break
                    case .exporting:
                        break
                    case .completed:
                        self.videoURL = compressedURL
                    case .failed:
                        break
                    case .cancelled:
                        break
                    }
                }
            }else{
                showAlertWithTitle(title: "Alert!", message: "Video Length cannot be more that 30Sec to upload!")
            }
    
        }
        picker.dismiss(animated: true, completion: nil);
    }
    
    func compressVideo(inputURL: URL, outputURL: URL, handler:@escaping (_ exportSession: AVAssetExportSession?)-> Void) {
            let urlAsset = AVURLAsset(url: inputURL, options: nil)
            guard let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality) else {
                handler(nil)
                return
            }
    
            exportSession.outputURL = outputURL
            exportSession.outputFileType = AVFileType.mov
            exportSession.shouldOptimizeForNetworkUse = true
            exportSession.exportAsynchronously { () -> Void in
                handler(exportSession)
            }
        }
    

    然后依次调用以下方法上载视频:

        // video Upload
    
        func requestAccessToTwitterAccount(videoURL:NSURL,fileSize:UInt32){
    
            let accountStore = ACAccountStore()
            let twitterAccountType = accountStore.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)
            accountStore.requestAccessToAccounts(with: twitterAccountType, options: nil) { (granted, error) in
    
                if granted {
                    let accounts = accountStore.accounts(with: twitterAccountType)
                    if (accounts?.count)! > 0 {
                        self.twitterAccount = accounts?.last as! ACAccount
                        self.uploadVideoToTwitter(videoURL: videoURL, fileSize: fileSize)
                    }
                else{
                        let error = "Please set your twitter account in Settings."
                        print(error)
                    }
                }
            else {
                print("App permissions are disabled in device twitter settings, please enable it.")
            }
        }
    }
        func uploadVideoToTwitter(videoURL:NSURL,fileSize: UInt32){
            print(videoURL.path!)
            if let videoData = NSData(contentsOfFile: videoURL.path!){
    
                self.tweetVideoInit(videoData: videoData, videoSize: Int(fileSize))
            }else{
                print("Something Wrong")
            }
        }
    
        func tweetVideoInit(videoData:NSData,videoSize:Int) {
    
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
    
            var params = [String:String]()
    
            params["command"] = "INIT"
            params["total_bytes"]  = String(videoData.length)
            params["media_type"]  = "video/m4v"
    
            print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                if error != nil {
                    print(error!)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            print(dictionary)
                            if let tweetID = dictionary["media_id_string"] as? String{
                                self.tweetVideoApped(videoData: videoData, videoSize: videoSize, mediaId: tweetID, chunk: 0)
                            }
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    
    
    
        func tweetVideoApped(videoData:NSData,videoSize:Int ,mediaId:String,chunk:NSInteger) {
    
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
    
            var params = [String:String]()
    
            params["command"] = "APPEND"
            params["media_id"]  = mediaId
            params["segment_index"]  = String(chunk)
    
            print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
            postRequest?.addMultipartData(videoData as Data!, withName: "media", type: "video/m4v", filename:"mediaFile")
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                print(responseData!)
                if let err = error {
                    print(err)
    
                }else{
                    self.tweetVideoFinalize(mediaId: mediaId)
                }
            })
        }
    
        func tweetVideoFinalize(mediaId:String) {
            let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
    
            var params = [String:String]()
            params["command"] = "FINALIZE"
            params["media_id"]  = mediaId
    
             print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                print(responseData!)
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            print(dictionary)
                            if self.videoURL != nil{
                                self.postStatusVideo(mediaId: mediaId)
                            }else{
                                print("Image Post Called")
                                if self.arrMediaIdString.count == self.arrImage.count{
                                    self.postStatusMultipleImages(arrMediaId: self.arrMediaIdString, statusText: "Demo Multi Images")
                                }
                            }
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    
        func postStatusMultipleImages(arrMediaId:[String],statusText:String) {
    
            let uploadURL = NSURL(string:"https://api.twitter.com/1.1/statuses/update.json")
    
            var params = [String:Any]()
            params["status"] = statusText
            params["media_ids"]  = arrMediaId
    
            print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
                print(responseData!)
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            print(dictionary)
                            print("video uploaded")
                            let alert = UIAlertController(title: "Success", message: "video uploaded successfully.", preferredStyle: UIAlertControllerStyle.alert)
                            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
                            self.present(alert, animated: true, completion: nil)
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    
        func postStatusVideo(mediaId:String) {
    
            let uploadURL = NSURL(string:"https://api.twitter.com/1.1/statuses/update.json")
    
            var params = [String:String]()
            params["status"] = "Testing Video"
            params["media_ids"]  = mediaId
    
             print(params)
    
            let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
                                        requestMethod: SLRequestMethod.POST,
                                        url: uploadURL as URL!,
                                        parameters: params)
    
            postRequest?.account = self.twitterAccount;
    
            postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
               print(responseData!)
                if let err = error {
                    print(err)
                }else{
                    do {
                        let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
                        if let dictionary = object as? [String: AnyObject] {
                            print(dictionary)
                            print("video uploaded")
                            let alert = UIAlertController(title: "Success", message: "video uploaded successfully.", preferredStyle: UIAlertControllerStyle.alert)
                            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
                            self.present(alert, animated: true, completion: nil)
                        }
                    }
                    catch {
                        print(error)
                    }
                }
            })
        }
    

    最后像这样使用:

    var fileSizeValue = getVideoSize(contentUrl: videoURL)
    requestAccessToTwitterAccount(videoURL: videoURL as NSURL, fileSize: UInt32(fileSizeValue))
    

    以及计算视频大小的函数:

    func getVideoSize(contentUrl:URL) -> UInt64{
        do {
            let fileAttribute: [FileAttributeKey : Any] = try FileManager.default.attributesOfItem(atPath: contentUrl.path)
            if let fileNumberSize: NSNumber = fileAttribute[FileAttributeKey.size] as? NSNumber {
                return UInt64(truncating: fileNumberSize)
            }
        } catch {
            print(error.localizedDescription)
        }
       return 0
    }
    

    希望这有帮助。