As a prerequisite for uploading videos, be sure to generate an API token and familiarize yourself with querying the Rewatch GraphQL API.
Uploading videos using the API
Uploading a video to Rewatch via the API is a multi-step process:
Execute an
initiateDirectVideoUpload
GraphQL mutation to receive a URL to upload the video file to, HTTP headers to include in the request, and an upload ID to use after the video has been uploaded.Issue an HTTP
PUT
request to the given URL, including the given headers, with the video file as the request body.Execute a
createVideoFromDirectUpload
mutation, passing the upload ID returned in the first step along with the video’s details, such as its title, description, initial collections, and visibility on the channel.
Here is a full example written in the Ruby programming language, using the graphql-client
library, that illustrates each step:
require "digest/md5"
require "json"
require "net/http"
require "uri"
require "graphql/client"
require "graphql/client/http"
# Initialize a GraphQL client that has introspected the Rewatch API schema
adapter = GraphQL::Client::HTTP.new("https://example-channel.rewatch.com/api/graphql") do
def headers(context)
{
"Authorization": "Token token=MY-API-TOKEN",
"Content-Type": "application/json",
}
end
end
schema = GraphQL::Client.load_schema(adapter)
client = GraphQL::Client.new(schema: schema, execute: adapter)
file_path = "/path/to/my-video.mp4"
file_data = File.read(file_path)
# Send a mutation query to initiate an upload. The response will contain
# a URL to upload the file data to and an upload id to use once the file
# has been uploaded.
INITIATE_UPLOAD_MUTATION = client.parse <<-'GRAPHQL'
mutation ($input: InitiateDirectVideoUploadInput!) {
initiateDirectVideoUpload(input: $input) {
uploadHeaders
uploadId
uploadUrl
errors {
message
path
}
}
}
GRAPHQL
query_response = client.query(
INITIATE_UPLOAD_MUTATION,
variables: {
input: {
byteSize: File.size(file_path),
checksum: Digest::MD5.base64digest(file_data),
contentType: "video/mp4",
filename: "my-video.mp4",
},
},
)
# Check for any query-level errors, such as a type mismatch.
if query_response.errors.any?
error_messages = query_response.errors.map(&:message)
puts "initiateDirectVideoUpload mutation failed: #{error_messages.join(", ")}"
exit 1
end
initiation_result = query_response.data.initiate_direct_video_upload
# Check for any mutation errors, such as passing an invalid media type or filename.
if initiation_result.errors.any?
error_messages = initiation_result.errors.map(&:message)
puts "initiateDirectVideoUpload mutation failed: #{error_messages.join(", ")}"
exit 1
end
# Using the upload URL and request headers returned from the mutation,
# construct an HTTP PUT request to upload the file data directly. upload_uri = URI(initiation_result.upload_url)
upload_headers = JSON.parse(initiation_result.upload_headers)
upload_request = Net::HTTP::Put.new(upload_uri)
upload_headers.each do |name, value|
upload_request[name] = value
end
upload_request.body = file_data
upload_response = Net::HTTP.start(upload_uri.host, upload_uri.port, use_ssl: true) do |http|
http.request upload_request
end
if upload_response.code.to_i >= 300
puts "Upload failed with status #{upload_response.code}: #{upload_response.message}."
exit 1
end
# Once the upload has finished, use the upload ID returned by the
# initation mutation to create a new video on the channel.
CREATE_VIDEO_MUTATION = client.parse <<-'GRAPHQL'
mutation ($input: CreateVideoFromDirectUploadInput!) {
createVideoFromDirectUpload(input: $input) {
video {
title
url
}
errors {
message
path
}
}
}
GRAPHQL
query_response = client.query(
CREATE_VIDEO_MUTATION,
variables: {
input: {
uploadId: initiation_result.upload_id,
title: "My Video",
description: "My super neat video.",
visibility: "ON_CHANNEL",
},
},
)
if query_response.errors.any?
error_messages = query_response.errors.map(&:message)
puts "createVideoFromDirectUpload mutation failed: #{error_messages.join(", ")}"
exit 1
end
create_video_result = query_response.data.create_video_from_direct_upload
if create_video_result.errors.any?
error_messages = create_video_result.errors.map(&:message)
puts "createVideoFromDirectUpload mutation failed: #{error_messages.join(", ")}"
exit 1
end
puts "Uploaded '#{create_video_result.video.title}' to #{create_video_result.video.url}!"