我正在尝试上传即使用我的设备分享视频到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表示以下限制 我不会超过。
有人可以帮我解决这个问题的原因。
答案 0 :(得分:1)
这是我之前使用的代码,对我来说效果很好。试试这个
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
答案 1 :(得分:0)
研究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
}
希望这有帮助。