Search code examples
iosswiftyoutubeswift3multipart

Uploading a video to youtube from iOS app returns 400


I have an iOS(swift) app in which I can log in through my google account and get an access token.

After retrieving the access token I am making a post request to YouTube for uploading the video.

The error returned is as follows

{error =
{code = 400;
errors =({domain = global;
location = part;
locationType = parameter;
message = \"Required parameter: part\";
reason = required;});
message = \"Required parameter: part\";};}"

Following is the code that I am using to make a post request.

 func postVideoToYouTube(token: String, callback: @escaping (Bool) -> Void){
        if videoPath == nil {
            return
        }
        var movieData: NSData?
        do {
            movieData = try NSData(contentsOfFile: (videoPath?.relativePath)!, options: NSData.ReadingOptions.alwaysMapped)
        } catch _ {
            movieData = nil
            return
        }


        let headers = ["Authorization": "Bearer \(token)"]
        let URL = try! URLRequest(url: "https://www.googleapis.com/upload/youtube/v3/videos", method: .post, headers: headers)
        print("Video Data",movieData)
        Alamofire.upload(multipartFormData: { multipartFormData in
            multipartFormData.append(movieData as! Data, withName: "video", fileName: "video.mp4", mimeType: "application/octet-stream")
        }, with: URL, encodingCompletion: {
            encodingResult in
            switch encodingResult {
            case .success(let upload, _, _):
                upload.responseJSON { response in
                    debugPrint("SUCCESS RESPONSE1: \(response)")
                }
            case .failure(let encodingError):

                print("ERROR RESPONSE: \(encodingError)")
            }
        })
    }

Earlier the error was 403 forbidden , but I have added "https://www.googleapis.com/auth/youtube.force-ssl" to scope and now I am getting a 400.

Any help will be appreciated. Thank you.


Solution

  • This line in the return data is interesting:

    Required parameter: part
    

    It tells you that a parameter named part is required, and you have not included that in your call so that is why you are getting an error.

    If you look at the Youtube API description you can see a description of the part parameter.

    For instance

    The part parameter serves two purposes in this operation. It identifies the properties that the write operation will set as well as the properties that the API response will include.

    And

    The following list contains the part names that you can include in the parameter value and the quota cost for each part:

    • contentDetails: 2

    • fileDetails: 1

    • id: 0

    • liveStreamingDetails: 2

    • localizations: 2

    • player: 0

    • processingDetails: 1

    • recordingDetails: 2

    • snippet: 2

    • statistics: 2

    • status: 2

    • suggestions: 1

    • topicDetails: 2

    OK..that may not make a lot of sense but fortunately there are some examples as well.

    Here is a link to an example using python.

    If you look at that example the interesting part (no pun intended) is here:

    # Call the API's videos.insert method to create and upload the video.
    insert_request = youtube.videos().insert(
        part=",".join(body.keys()),
    

    OK, so we join the keys of something called body and that ends out being the value of the part parameter.

    Next question...how is body defined?

    body=dict(
      snippet=dict(
        title=options.title,
        description=options.description,
        tags=tags,
        categoryId=options.category
      ),
      status=dict(
        privacyStatus=options.privacyStatus
      )
    )
    

    So...the keys of body must be snippet and status. If you look at the valid values mentioned in the list described by "The following list contains the part names that you can include in the parameter value" above in my answer, you'll see both snippet and status there, so they seems valid.

    So in short, you should add the part parameter when you do a POST request to the YouTube API. The value of that parameter could be snippet, status but you should probably read up on exactly what that means and whether you should use something else.

    Hope that helps you.