runapi-happyhorse 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e0fbd41ba815c6b83de99cd5c32f46981293c448a0e10fa9d5894403f26868f
4
- data.tar.gz: 1b8ed70e59a12339fc45ead0a013cd78d1f3c52eb638faa90d750dcdab603ae4
3
+ metadata.gz: 2c4f0f454f1eb15878f3c4edd3f7d958db1777e5ffb6260c0f29e0774fa587bd
4
+ data.tar.gz: 0c0f9d96f07ed1d893a531df62c42f5c2896b1c61d56e751635b973d7608d6f0
5
5
  SHA512:
6
- metadata.gz: 8b4b0986bf2e5c8ac7c1f7488c84237cb85933397a2af5760a254fb845b958a8b6a5b65d3f7353fb3680b35fb1aa0a4f628177423dfc2eb5077c12ca84b975b1
7
- data.tar.gz: 45314c2e79d8f9ff6bee7e53811580dd2654aa94d0d4f80a4fabae768c58bcc7a28ddb3f145293bb20d2c8300f5e026fd70ff696549998109f3a955403bc0277
6
+ metadata.gz: 1464ac2c22e0349fdb59df6a910a8afd1ae31be12831847359182b09da136ed7e332f9a3df0d32bbe2a5ada0c711a2e78eb14f3ecb509e8f5e25640100de8490
7
+ data.tar.gz: 0cc07a34f20984589248c3571a528e35085194557e5477fbed9b524ecc78dacf308511dc0a68750488ff5da5c926b454d42e7be743d51d8b061ce587fd3c6975
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # HappyHorse API Ruby SDK for RunAPI
2
2
 
3
- The happyhorse ai api Ruby SDK is the language-specific package for HappyHorse on RunAPI. Use this package for text, image, reference-to-video, and edit-video workflows that need JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
3
+ The happyhorse ai api Ruby SDK is the language-specific package for HappyHorse on RunAPI. Use this package for text, image, and edit-video workflows that need JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
4
4
 
5
5
  ## Install
6
6
 
@@ -15,15 +15,16 @@ require "runapi-happyhorse"
15
15
 
16
16
  client = RunApi::HappyHorse::Client.new
17
17
  video = client.text_to_video.run(
18
- model: "happyhorse-text-to-video",
19
- prompt: "A tiny paper horse gallops through a miniature cardboard city at night.",
20
- resolution: "1080p",
18
+ model: "happyhorse-character",
19
+ prompt: "Character1 walks through a miniature cardboard city at night.",
20
+ reference_image_urls: ["https://cdn.runapi.ai/public/samples/reference-1.jpg"],
21
+ output_resolution: "1080p",
21
22
  aspect_ratio: "16:9",
22
- duration: 5
23
+ duration_seconds: 5
23
24
  )
24
25
  ```
25
26
 
26
- For image-to-video, call `client.image_to_video.run` with `model: "happyhorse-image-to-video"` and exactly one `image_urls` entry. For reference-to-video, call `client.reference_to_video.run` with `model: "happyhorse-reference-to-video"` and 1-9 `reference_image` entries. For edit-video, call `client.edit_video.run` with `model: "happyhorse-video-edit"`, one `video_url`, and optional `reference_image` entries.
27
+ For image-to-video, call `client.image_to_video.run` with `model: "happyhorse-image-to-video"` and exactly one `image_urls` entry. For character-guided text-to-video, call `client.text_to_video.run` with `model: "happyhorse-character"` and 1-9 `reference_image_urls` entries. For edit-video, call `client.edit_video.run` with `model: "happyhorse-edit-video"`, one `video_url`, and optional `reference_image` entries.
27
28
 
28
29
  ## Links
29
30
 
@@ -31,8 +32,8 @@ For image-to-video, call `client.image_to_video.run` with `model: "happyhorse-im
31
32
  - SDK docs: https://runapi.ai/docs#sdk-happyhorse
32
33
  - Product docs: https://runapi.ai/docs#happyhorse
33
34
  - Image-to-video pricing and rate limits: https://runapi.ai/models/happyhorse/image-to-video
34
- - Reference-to-video pricing and rate limits: https://runapi.ai/models/happyhorse/reference-to-video
35
- - Edit-video pricing and rate limits: https://runapi.ai/models/happyhorse/video-edit
35
+ - Character pricing and rate limits: https://runapi.ai/models/happyhorse/character
36
+ - Edit-video pricing and rate limits: https://runapi.ai/models/happyhorse/edit-video
36
37
  - Pricing and rate limits: https://runapi.ai/models/happyhorse/text-to-video
37
38
  - Provider comparison: https://runapi.ai/providers/alibaba
38
39
  - Full catalog: https://runapi.ai/models
@@ -3,7 +3,7 @@
3
3
  module RunApi
4
4
  module HappyHorse
5
5
  class Client
6
- attr_reader :text_to_video, :image_to_video, :reference_to_video, :edit_video
6
+ attr_reader :text_to_video, :image_to_video, :edit_video
7
7
 
8
8
  def initialize(api_key: nil, **options)
9
9
  @api_key = Core::Auth.resolve_api_key(api_key)
@@ -12,7 +12,6 @@ module RunApi
12
12
  http = client_options.http_client || Core::HttpClient.new(client_options)
13
13
  @text_to_video = Resources::TextToVideo.new(http)
14
14
  @image_to_video = Resources::ImageToVideo.new(http)
15
- @reference_to_video = Resources::ReferenceToVideo.new(http)
16
15
  @edit_video = Resources::EditVideo.new(http)
17
16
  end
18
17
  end
@@ -36,14 +36,14 @@ module RunApi
36
36
  def validate_params!(params)
37
37
  raise Core::ValidationError, "model is required" unless param(params, :model) == Types::EDIT_VIDEO_MODEL
38
38
  raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
39
- raise Core::ValidationError, "video_url is required" unless param(params, :video_url)
39
+ raise Core::ValidationError, "source_video_url is required" unless param(params, :source_video_url)
40
40
 
41
- reference_image = param(params, :reference_image)
42
- if reference_image && (!reference_image.is_a?(Array) || !REFERENCE_IMAGE_RANGE.cover?(reference_image.size))
43
- raise Core::ValidationError, "reference_image must include at most #{REFERENCE_IMAGE_RANGE.max} entries"
41
+ reference_image_urls = param(params, :reference_image_urls)
42
+ if reference_image_urls && (!reference_image_urls.is_a?(Array) || !REFERENCE_IMAGE_RANGE.cover?(reference_image_urls.size))
43
+ raise Core::ValidationError, "reference_image_urls must include at most #{REFERENCE_IMAGE_RANGE.max} entries"
44
44
  end
45
45
 
46
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
46
+ validate_optional!(params, :output_resolution, Types::OUTPUT_RESOLUTIONS)
47
47
  validate_optional!(params, :audio_setting, Types::AUDIO_SETTINGS)
48
48
  validate_integer_range!(params, :seed, Types::SEED_RANGE)
49
49
  end
@@ -52,8 +52,7 @@ module RunApi
52
52
  value = param(params, key)
53
53
  return unless value
54
54
 
55
- integer = Integer(value, exception: false)
56
- return if integer && range.cover?(integer)
55
+ return if value.is_a?(Integer) && range.cover?(value)
57
56
 
58
57
  raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
59
58
  end
@@ -10,7 +10,6 @@ module RunApi
10
10
 
11
11
  RESPONSE_CLASS = Types::ImageToVideoResponse
12
12
  COMPLETED_RESPONSE_CLASS = Types::CompletedImageToVideoResponse
13
- IMAGE_URLS_MAX = 1
14
13
 
15
14
  def initialize(http)
16
15
  @http = http
@@ -35,13 +34,10 @@ module RunApi
35
34
 
36
35
  def validate_params!(params)
37
36
  raise Core::ValidationError, "model is required" unless param(params, :model) == Types::IMAGE_TO_VIDEO_MODEL
37
+ raise Core::ValidationError, "first_frame_image_url is required" unless param(params, :first_frame_image_url)
38
38
 
39
- image_urls = param(params, :image_urls)
40
- raise Core::ValidationError, "image_urls is required" unless image_urls.is_a?(Array) && image_urls.any?
41
- raise Core::ValidationError, "image_urls supports at most #{IMAGE_URLS_MAX} entry" if image_urls.size > IMAGE_URLS_MAX
42
-
43
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
44
- validate_integer_range!(params, :duration, Types::DURATION_RANGE)
39
+ validate_optional!(params, :output_resolution, Types::OUTPUT_RESOLUTIONS)
40
+ validate_integer_range!(params, :duration_seconds, Types::DURATION_RANGE)
45
41
  validate_integer_range!(params, :seed, Types::SEED_RANGE)
46
42
  end
47
43
 
@@ -49,8 +45,7 @@ module RunApi
49
45
  value = param(params, key)
50
46
  return unless value
51
47
 
52
- integer = Integer(value, exception: false)
53
- return if integer && range.cover?(integer)
48
+ return if value.is_a?(Integer) && range.cover?(value)
54
49
 
55
50
  raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
56
51
  end
@@ -10,6 +10,7 @@ module RunApi
10
10
 
11
11
  RESPONSE_CLASS = Types::TextToVideoResponse
12
12
  COMPLETED_RESPONSE_CLASS = Types::CompletedTextToVideoResponse
13
+ REFERENCE_IMAGE_URLS_RANGE = (1..9)
13
14
 
14
15
  def initialize(http)
15
16
  @http = http
@@ -33,12 +34,22 @@ module RunApi
33
34
  private
34
35
 
35
36
  def validate_params!(params)
36
- raise Core::ValidationError, "model is required" unless param(params, :model) == Types::TEXT_TO_VIDEO_MODEL
37
+ model = param(params, :model)
38
+ raise Core::ValidationError, "model is required" unless Types::TEXT_TO_VIDEO_MODELS.include?(model)
37
39
  raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
38
40
 
39
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
41
+ reference_image_urls = param(params, :reference_image_urls)
42
+ if model == Types::CHARACTER_MODEL
43
+ unless reference_image_urls.is_a?(Array) && REFERENCE_IMAGE_URLS_RANGE.cover?(reference_image_urls.size)
44
+ raise Core::ValidationError, "reference_image_urls must include between #{REFERENCE_IMAGE_URLS_RANGE.min} and #{REFERENCE_IMAGE_URLS_RANGE.max} entries"
45
+ end
46
+ elsif reference_image_urls
47
+ raise Core::ValidationError, "reference_image_urls is only supported for #{Types::CHARACTER_MODEL}"
48
+ end
49
+
50
+ validate_optional!(params, :output_resolution, Types::OUTPUT_RESOLUTIONS)
40
51
  validate_optional!(params, :aspect_ratio, Types::ASPECT_RATIOS)
41
- validate_integer_range!(params, :duration, Types::DURATION_RANGE)
52
+ validate_integer_range!(params, :duration_seconds, Types::DURATION_RANGE)
42
53
  validate_integer_range!(params, :seed, Types::SEED_RANGE)
43
54
  end
44
55
 
@@ -46,8 +57,7 @@ module RunApi
46
57
  value = param(params, key)
47
58
  return unless value
48
59
 
49
- integer = Integer(value, exception: false)
50
- return if integer && range.cover?(integer)
60
+ return if value.is_a?(Integer) && range.cover?(value)
51
61
 
52
62
  raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
53
63
  end
@@ -4,12 +4,13 @@ module RunApi
4
4
  module HappyHorse
5
5
  module Types
6
6
  TEXT_TO_VIDEO_MODEL = "happyhorse-text-to-video"
7
+ CHARACTER_MODEL = "happyhorse-character"
8
+ TEXT_TO_VIDEO_MODELS = [TEXT_TO_VIDEO_MODEL, CHARACTER_MODEL].freeze
7
9
  IMAGE_TO_VIDEO_MODEL = "happyhorse-image-to-video"
8
- REFERENCE_TO_VIDEO_MODEL = "happyhorse-reference-to-video"
9
- EDIT_VIDEO_MODEL = "happyhorse-video-edit"
10
- RESOLUTIONS = %w[720p 1080p].freeze
10
+ EDIT_VIDEO_MODEL = "happyhorse-edit-video"
11
+ OUTPUT_RESOLUTIONS = %w[720p 1080p].freeze
11
12
  ASPECT_RATIOS = %w[16:9 9:16 1:1 4:3 3:4].freeze
12
- AUDIO_SETTINGS = %w[auto origin].freeze
13
+ AUDIO_SETTINGS = %w[auto original].freeze
13
14
  DURATION_RANGE = (3..15)
14
15
  SEED_RANGE = (0..2_147_483_647)
15
16
 
@@ -30,8 +31,6 @@ module RunApi
30
31
 
31
32
  ImageToVideoResponse = TextToVideoResponse
32
33
  CompletedImageToVideoResponse = CompletedTextToVideoResponse
33
- ReferenceToVideoResponse = TextToVideoResponse
34
- CompletedReferenceToVideoResponse = CompletedTextToVideoResponse
35
34
  EditVideoResponse = TextToVideoResponse
36
35
  CompletedEditVideoResponse = CompletedTextToVideoResponse
37
36
  end
@@ -4,7 +4,6 @@ require "runapi/core"
4
4
  require_relative "happyhorse/types"
5
5
  require_relative "happyhorse/resources/edit_video"
6
6
  require_relative "happyhorse/resources/image_to_video"
7
- require_relative "happyhorse/resources/reference_to_video"
8
7
  require_relative "happyhorse/resources/text_to_video"
9
8
  require_relative "happyhorse/client"
10
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runapi-happyhorse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - RunAPI
@@ -15,18 +15,17 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.2.4
18
+ version: 0.2.5
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.2.4
25
+ version: 0.2.5
26
26
  description: The happyhorse ai api Ruby SDK is the language-specific package for HappyHorse
27
- on RunAPI. Use this package for text, image, reference-to-video, and edit-video
28
- workflows that need JSON request bodies, task status lookup, and consistent RunAPI
29
- errors in Ruby.
27
+ on RunAPI. Use this package for text, image, and edit-video workflows that need
28
+ JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
30
29
  email:
31
30
  - contact@runapi.ai
32
31
  executables: []
@@ -41,7 +40,6 @@ files:
41
40
  - lib/runapi/happyhorse/client.rb
42
41
  - lib/runapi/happyhorse/resources/edit_video.rb
43
42
  - lib/runapi/happyhorse/resources/image_to_video.rb
44
- - lib/runapi/happyhorse/resources/reference_to_video.rb
45
43
  - lib/runapi/happyhorse/resources/text_to_video.rb
46
44
  - lib/runapi/happyhorse/types.rb
47
45
  homepage: https://runapi.ai/models/happyhorse
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RunApi
4
- module HappyHorse
5
- module Resources
6
- class ReferenceToVideo
7
- include RunApi::Core::ResourceHelpers
8
-
9
- ENDPOINT = "/api/v1/happyhorse/reference_to_video"
10
-
11
- RESPONSE_CLASS = Types::ReferenceToVideoResponse
12
- COMPLETED_RESPONSE_CLASS = Types::CompletedReferenceToVideoResponse
13
- REFERENCE_IMAGE_RANGE = (1..9)
14
-
15
- def initialize(http)
16
- @http = http
17
- end
18
-
19
- def run(**params)
20
- task = create(**params)
21
- poll_until_complete { get(task.id) }
22
- end
23
-
24
- def create(**params)
25
- params = compact_params(params)
26
- validate_params!(params)
27
- request(:post, ENDPOINT, body: params)
28
- end
29
-
30
- def get(id)
31
- request(:get, "#{ENDPOINT}/#{id}")
32
- end
33
-
34
- private
35
-
36
- def validate_params!(params)
37
- raise Core::ValidationError, "model is required" unless param(params, :model) == Types::REFERENCE_TO_VIDEO_MODEL
38
- raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
39
-
40
- reference_image = param(params, :reference_image)
41
- unless reference_image.is_a?(Array) && REFERENCE_IMAGE_RANGE.cover?(reference_image.size)
42
- raise Core::ValidationError, "reference_image must include between #{REFERENCE_IMAGE_RANGE.min} and #{REFERENCE_IMAGE_RANGE.max} entries"
43
- end
44
-
45
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
46
- validate_optional!(params, :aspect_ratio, Types::ASPECT_RATIOS)
47
- validate_integer_range!(params, :duration, Types::DURATION_RANGE)
48
- validate_integer_range!(params, :seed, Types::SEED_RANGE)
49
- end
50
-
51
- def validate_integer_range!(params, key, range)
52
- value = param(params, key)
53
- return unless value
54
-
55
- integer = Integer(value, exception: false)
56
- return if integer && range.cover?(integer)
57
-
58
- raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
59
- end
60
- end
61
- end
62
- end
63
- end