coconutrb 2.4.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5d080f48508838a97c4a7aa3d7022008741ca5b2
4
- data.tar.gz: be3d0ec286c2d79774e68edec3b9c1634d1dd32b
2
+ SHA256:
3
+ metadata.gz: 7aa3f69b0c70c759598d976f4d17b5bd0fd7f6606af16d0963997357de1990f6
4
+ data.tar.gz: fc07ef5a74c85511ecd75d0f2e1d3106828ba843f887ff50a9f6274d868a44ad
5
5
  SHA512:
6
- metadata.gz: bd2260ce0933b9bbcc6906285c1fa3416caf08845e7ee4b30f22ed29c912e67dde5abe17b1c6b669072bcc281b216275f520496e7efd8f6d97de9030988c34b1
7
- data.tar.gz: 12825f9470666421d7dbbb5755f035eb818dd17454d9307cf6e83f71c94dd37f1755d5ed479cd631c17303d4a2fc4789befcfa4dd460b07353272a46daadc78a
6
+ metadata.gz: 640e39db9a079f9a77560a0c600c25debdab49e69db0c91e551f872a9060a8e6a1e90c0ad305c73df566d31d578fe6cce9cee431380f67c66fe63a0ed2aff419
7
+ data.tar.gz: 9ad2757fb32aee75a13051ad793483ba06c332519cdfb4638ef0fb5969e52c1b8b2e1e1b0e91d3083904b7a723f7e5d18b5380a5aa6ef0a0e1841da5fb78b530
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .testenv
3
+ run_tests
4
+ *.gem
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # Coconut Ruby Library
2
+
3
+ The Coconut Ruby library provides access to the Coconut API for encoding videos, packaging media files into HLS and MPEG-Dash, generating thumbnails and GIF animation.
4
+
5
+ This library is only compatible with the Coconut API v2.
6
+
7
+ ## Documentation
8
+
9
+ See the [full documentation](https://docs.coconut.co).
10
+
11
+ ## Installation
12
+
13
+ You can install it via rubygems:
14
+
15
+ ```console
16
+ gem install coconutrb
17
+ ```
18
+
19
+ ### Bundler
20
+
21
+ In Gemfile:
22
+
23
+ ```ruby
24
+ gem 'coconutrb', '~> 3.0.0'
25
+ ```
26
+
27
+ And then, type in your terminal:
28
+
29
+ ```console
30
+ bundle install
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ The library needs you to set your API key which can be found in your [dashboard](https://app.coconut.co/api). Webhook URL and storage settings are optional but are very convenient because you set them only once.
36
+
37
+ ```ruby
38
+ Coconut.api_key = 'k-api-key'
39
+
40
+ Coconut.notification = {
41
+ type: "http",
42
+ url: "https://yoursite/api/coconut/webhook"
43
+ }
44
+
45
+ Coconut.storage = {
46
+ service: "s3",
47
+ bucket: "my-bucket",
48
+ region: "us-east-1",
49
+ credentials: {
50
+ access_key_id: "access-key",
51
+ secret_access_key: "secret-key"
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## Creating a job
57
+
58
+ ```ruby
59
+ Coconut::Job.create(
60
+ input: { url: "https://mysite/path/file.mp4" },
61
+ outputs: {
62
+ "jpg:300x": { path: "/image.jpg" },
63
+ "mp4:1080p": { path: "/1080p.mp4" },
64
+ "httpstream": {
65
+ hls: { path: "hls/" }
66
+ }
67
+ }
68
+ )
69
+ ```
70
+
71
+ ## Getting information about a job
72
+
73
+ ```ruby
74
+ Coconut::Job.retrieve("OolQXaiU86NFki")
75
+ ```
76
+
77
+ ## Retrieving metadata
78
+
79
+ ```ruby
80
+ Coconut::Metadata.retrieve("OolQXaiU86NFki")
81
+
82
+ ```
83
+
84
+ ## Per-request configuration
85
+
86
+ ```ruby
87
+ cli = Coconut::Client.new(api_key: "k-api-key-prod")
88
+ Coconut::Job.create(job, client: cli)
89
+ ```
90
+
91
+ *Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php).*
data/coconutrb.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(::File.join(::File.dirname(__FILE__), "lib"))
2
+
3
+ require "coconut/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "coconutrb"
7
+ gem.version = Coconut::VERSION
8
+ gem.summary = "Client library to transcode videos with coconut.co"
9
+ gem.description = "Official client library to transcode videos with Coconut Cloud Service"
10
+ gem.author = "Coconut"
11
+ gem.email = "support@coconut.co"
12
+ gem.homepage = "https://coconut.co"
13
+ gem.license = "MIT"
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- test/*`.split("\n")
16
+ gem.require_paths = ["lib"]
17
+ gem.add_runtime_dependency "http"
18
+ end
data/lib/coconut.rb ADDED
@@ -0,0 +1,50 @@
1
+ require "coconut/api"
2
+ require "coconut/error"
3
+ require "coconut/client"
4
+ require "coconut/job"
5
+ require "coconut/metadata"
6
+ require "coconut/version"
7
+
8
+ module Coconut
9
+ ENDPOINT = "https://api.coconut.co/v2"
10
+
11
+ def self.api_key=(key)
12
+ @api_key = key
13
+ end
14
+
15
+ def self.api_key
16
+ @api_key
17
+ end
18
+
19
+ def self.region=(region)
20
+ @region = region
21
+ end
22
+
23
+ def self.region
24
+ @region
25
+ end
26
+
27
+ def self.endpoint=(endpoint)
28
+ @endpoint = endpoint
29
+ end
30
+
31
+ def self.endpoint
32
+ @endpoint
33
+ end
34
+
35
+ def self.notification=(notification)
36
+ @notification = notification
37
+ end
38
+
39
+ def self.notification
40
+ @notification
41
+ end
42
+
43
+ def self.storage=(storage)
44
+ @storage = storage
45
+ end
46
+
47
+ def self.storage
48
+ @storage
49
+ end
50
+ end
@@ -0,0 +1,38 @@
1
+ require "http"
2
+
3
+ module Coconut
4
+ # Coconut::API is responsible for making API requests.
5
+ # It takes a Coconut::Client to send api_key, endpoint and region.
6
+ class API
7
+ def self.headers(cli)
8
+ if cli.api_key.nil?
9
+ raise Coconut::Error, "You must specify an API key with Coconut.api_key="
10
+ end
11
+
12
+ HTTP.basic_auth(user: cli.api_key, pass: "").
13
+ headers(:user_agent => "Coconut/v2 RubyBindings/#{Coconut::VERSION}")
14
+ end
15
+
16
+ def self.request(verb, path, options={})
17
+ cli = options[:client] || Coconut.default_client
18
+
19
+ case verb
20
+ when :get
21
+ resp = headers(cli).get("#{cli.endpoint}#{path}")
22
+ when :post
23
+ resp = headers(cli).post("#{cli.endpoint}#{path}", json: options[:json])
24
+ end
25
+
26
+ if resp.code > 399
27
+ # if response is 400 or 401, we return the error message and error code
28
+ if resp.code.between?(400, 401)
29
+ raise Coconut::Error, "#{resp.parse["message"]} (code=#{resp.parse["error_code"]})"
30
+ else
31
+ raise Coconut::Error, "Server returned HTTP status #{resp.code}."
32
+ end
33
+ end
34
+
35
+ return resp.parse
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ module Coconut
2
+ def self.default_client
3
+ Client.new({
4
+ api_key: Coconut.api_key,
5
+ region: Coconut.region,
6
+ endpoint: Coconut.endpoint
7
+ })
8
+ end
9
+
10
+ class Client
11
+ attr_accessor :api_key, :endpoint, :region
12
+
13
+ def initialize(options={})
14
+ @api_key = options[:api_key]
15
+ @region = options[:region]
16
+ @endpoint = options[:endpoint]
17
+ end
18
+
19
+ def endpoint
20
+ # if endpoint set, we return it
21
+ if @endpoint
22
+ return @endpoint
23
+ end
24
+ # if no endpoint but region is given, we
25
+ # build the endpoint following https://api-region.coconut.co/v2
26
+ if @region
27
+ return "https://api-#{@region}.coconut.co/v2"
28
+ end
29
+
30
+ # by default:
31
+ return Coconut::ENDPOINT
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Coconut
2
+ class Error < RuntimeError; end
3
+ end
@@ -0,0 +1,42 @@
1
+ module Coconut
2
+ class Job < API
3
+ attr_reader :id, :created_at, :completed_at, :status, :progress, :errors, :output_urls
4
+
5
+ def initialize(attrs={})
6
+ @id = attrs["id"]
7
+ @created_at = attrs["created_at"]
8
+ @completed_at = attrs["completed_at"]
9
+ @status = attrs["status"]
10
+ @progress = attrs["progress"]
11
+ @errors = attrs["errors"]
12
+ @output_urls = attrs["output_urls"]
13
+ end
14
+
15
+ def self.retrieve(job_id, options={})
16
+ resp = API.request(:get, "/jobs/#{job_id}", options)
17
+ return Job.new(resp)
18
+ end
19
+
20
+ def self.create(job, options={})
21
+ resp = API.request(:post, "/jobs", options.merge({
22
+ json: apply_settings(job)
23
+ }))
24
+
25
+ return Job.new(resp)
26
+ end
27
+
28
+ def self.apply_settings(job)
29
+ if notification = Coconut.notification
30
+ job[:notification] ||= {}
31
+ job[:notification].merge!(notification)
32
+ end
33
+
34
+ if storage = Coconut.storage
35
+ job[:storage] ||= {}
36
+ job[:storage].merge!(storage)
37
+ end
38
+
39
+ return job
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ module Coconut
2
+ class Metadata
3
+ def self.retrieve(job_id, options={})
4
+ API.request(:get, "/metadata/jobs/#{job_id}/#{options.delete(:key)}", options)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Coconut
2
+ VERSION = "3.0.0"
3
+ end
@@ -0,0 +1,90 @@
1
+ $LOAD_PATH.unshift(::File.join(::File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require "test/unit"
4
+ require "coconut"
5
+
6
+ class CoconutTest < Test::Unit::TestCase
7
+ INPUT_URL = "https://s3-eu-west-1.amazonaws.com/files.coconut.co/bbb_800k.mp4"
8
+
9
+ def setup
10
+ Coconut.api_key = ENV["COCONUT_API_KEY"]
11
+ Coconut.endpoint = ENV["COCONUT_ENDPOINT"]
12
+
13
+ Coconut.storage = {
14
+ service: "s3",
15
+ region: ENV["AWS_REGION"],
16
+ credentials: { access_key_id: ENV["AWS_ACCESS_KEY_ID"], secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"] },
17
+ bucket: ENV["AWS_BUCKET"],
18
+ path: "/coconutrb/tests/"
19
+ }
20
+
21
+ Coconut.notification = {
22
+ type: "http",
23
+ url: ENV["COCONUT_WEBHOOK_URL"]
24
+ }
25
+ end
26
+
27
+ def create_job(j={}, options={})
28
+ Coconut::Job.create({
29
+ input: { url: INPUT_URL },
30
+ outputs: {
31
+ mp4: { path: "/test_create_job.mp4", duration: 1 }
32
+ }
33
+ }.merge(j), options)
34
+ end
35
+
36
+ def test_coconut_api_key
37
+ Coconut.api_key = "apikey"
38
+ assert "apikey", Coconut.api_key
39
+ end
40
+
41
+ def test_coconut_region
42
+ Coconut.region = "us-east-1"
43
+ assert "us-east-1", Coconut.region
44
+ end
45
+
46
+ def test_coconut_default_endpoint
47
+ assert "https://api.coconut.co/v2", Coconut.endpoint
48
+ end
49
+
50
+ def test_coconut_endpoint_by_region
51
+ Coconut.region = "us-west-2"
52
+ assert "https://api-us-west-2.coconut.co/v2", Coconut.endpoint
53
+ end
54
+
55
+ def test_overwrite_endpoint
56
+ myendpoint = "https://coconut-private/v2"
57
+ Coconut.endpoint = myendpoint
58
+
59
+ assert myendpoint, Coconut.endpoint
60
+ end
61
+
62
+ def test_create_job
63
+ job = create_job
64
+ assert job.is_a?(Coconut::Job)
65
+ assert_not_nil job.id
66
+ assert_equal "job.starting", job.status
67
+ end
68
+
69
+ def test_retrieve_job
70
+ job = Coconut::Job.retrieve(create_job.id)
71
+ assert job.is_a?(Coconut::Job)
72
+ assert_not_nil job.id
73
+ assert_equal "job.starting", job.status
74
+ end
75
+
76
+ def test_create_job_error
77
+ create_job(input: {url: "notvalidurl"})
78
+ rescue => e
79
+ assert_equal e.class, Coconut::Error
80
+ end
81
+
82
+ def test_retrieve_metadata
83
+ job = create_job
84
+ sleep 10
85
+
86
+ md = Coconut::Metadata.retrieve(job.id)
87
+ assert md.is_a?(Hash)
88
+ assert_not_nil md["metadata"]["input"]
89
+ end
90
+ end
metadata CHANGED
@@ -1,37 +1,47 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coconutrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Bruno Celeste
7
+ - Coconut
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-18 00:00:00.000000000 Z
11
+ date: 2021-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: multi_json
14
+ name: http
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
27
- description: Official client library to transcode videos with coconut cloud service
28
- email: bruno@coconut.co
26
+ version: '0'
27
+ description: Official client library to transcode videos with Coconut Cloud Service
28
+ email: support@coconut.co
29
29
  executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
- - lib/coconutrb.rb
34
- homepage: http://coconut.co
33
+ - ".gitignore"
34
+ - README.md
35
+ - coconutrb.gemspec
36
+ - lib/coconut.rb
37
+ - lib/coconut/api.rb
38
+ - lib/coconut/client.rb
39
+ - lib/coconut/error.rb
40
+ - lib/coconut/job.rb
41
+ - lib/coconut/metadata.rb
42
+ - lib/coconut/version.rb
43
+ - test/coconut_test.rb
44
+ homepage: https://coconut.co
35
45
  licenses:
36
46
  - MIT
37
47
  metadata: {}
@@ -50,9 +60,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
60
  - !ruby/object:Gem::Version
51
61
  version: '0'
52
62
  requirements: []
53
- rubyforge_project:
54
- rubygems_version: 2.5.2.3
63
+ rubygems_version: 3.1.4
55
64
  signing_key:
56
65
  specification_version: 4
57
66
  summary: Client library to transcode videos with coconut.co
58
- test_files: []
67
+ test_files:
68
+ - test/coconut_test.rb
data/lib/coconutrb.rb DELETED
@@ -1,135 +0,0 @@
1
- require "net/http"
2
- require "multi_json"
3
- require "uri"
4
-
5
- module Coconut
6
- class Error < RuntimeError; end
7
-
8
- COCONUT_URL = ENV["COCONUT_URL"] || "https://api.coconut.co"
9
- USER_AGENT = "Coconut/2.4.0 (Ruby)"
10
-
11
- API_KEY = ENV["COCONUT_API_KEY"] unless const_defined?(:COCONUT_API_KEY)
12
-
13
- def self.submit(config_content, api_key=nil)
14
- api_key ||= API_KEY
15
- uri = URI("#{COCONUT_URL}/v1/job")
16
- headers = {"User-Agent" => USER_AGENT, "Content-Type" => "text/plain", "Accept" => "application/json"}
17
-
18
- req = Net::HTTP::Post.new(uri.path, headers)
19
- req.basic_auth api_key, ''
20
- req.body = config_content
21
-
22
- response = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme.include?("https")) do |http|
23
- http.request(req)
24
- end
25
-
26
- return MultiJson.decode(response.body)
27
- end
28
-
29
- def self.submit!(config_content, opts={})
30
- result = submit(config_content, opts)
31
- if result["status"] == "error"
32
- raise Error, "#{result["message"]} (#{result["error_code"]})"
33
- else
34
- return result
35
- end
36
- end
37
-
38
- def self.get(path, api_key=nil)
39
- api_key ||= API_KEY
40
- uri = URI("#{COCONUT_URL}#{path}")
41
- headers = {"User-Agent" => USER_AGENT, "Content-Type" => "text/plain", "Accept" => "application/json"}
42
-
43
- req = Net::HTTP::Get.new(uri.path, headers)
44
- req.basic_auth api_key, ''
45
-
46
- response = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme.include?("https")) do |http|
47
- http.request(req)
48
- end
49
-
50
- if response.code.to_i != 200
51
- return nil
52
- else
53
- return MultiJson.decode(response.body)
54
- end
55
- end
56
-
57
- def self.config(options={})
58
- if conf_file = options[:conf]
59
- raise Error, "Config file `#{conf_file}' not found" if ! File.exists?(conf_file)
60
- conf = File.read(conf_file).strip.split("\n")
61
- else
62
- conf = []
63
- end
64
-
65
- if vars = options[:vars]
66
- vars.each do |name,value|
67
- conf << "var #{name} = #{value}"
68
- end
69
- end
70
-
71
- if source = options[:source]
72
- conf << "set source = #{source}"
73
- end
74
-
75
- if webhook = options[:webhook]
76
- if webhook.is_a?(Hash)
77
- webhook = hash_params_to_string(webhook)
78
- end
79
-
80
- conf << "set webhook = #{webhook}"
81
- end
82
-
83
- if api_version = options[:api_version]
84
- conf << "set api_version = #{api_version}"
85
- end
86
-
87
- if outputs = options[:outputs]
88
- outputs.each do |format, cdn|
89
- if cdn.is_a?(Hash)
90
- cdn = hash_params_to_string(cdn)
91
- end
92
-
93
- conf << "-> #{format} = #{cdn}"
94
- end
95
- end
96
-
97
- new_conf = []
98
-
99
- new_conf.concat conf.select{|l| l.start_with?("var")}.sort
100
- new_conf << ""
101
- new_conf.concat conf.select{|l| l.start_with?("set")}.sort
102
- new_conf << ""
103
- new_conf.concat conf.select{|l| l.start_with?("->")}.sort
104
-
105
- return new_conf.join("\n")
106
- end
107
-
108
- def self.hash_params_to_string(params)
109
- params.map{|k,v|
110
- if k.to_s == "url"
111
- "#{v}"
112
- else
113
- "#{k}=#{v}"
114
- end
115
- }.join(", ")
116
- end
117
-
118
- class Job
119
- def self.create(options={})
120
- Coconut.submit(Coconut.config(options), options[:api_key])
121
- end
122
-
123
- def self.get(jid, api_key=nil)
124
- Coconut.get("/v1/jobs/#{jid}", api_key)
125
- end
126
-
127
- def self.get_all_metadata(jid, api_key=nil)
128
- Coconut.get("/v1/metadata/jobs/#{jid}", api_key)
129
- end
130
-
131
- def self.get_metadata_for(jid, source_or_output, api_key=nil)
132
- Coconut.get("/v1/metadata/jobs/#{jid}/#{source_or_output}", api_key)
133
- end
134
- end
135
- end