Skip to content

Commit 2d270d3

Browse files
committed
Added method to obtain URL from asset ID
URLs are only valid for a limited time, if the asset ID is known, a valid URL can be obtained from the API.
1 parent f7fb0fe commit 2d270d3

File tree

3 files changed

+48
-24
lines changed

3 files changed

+48
-24
lines changed

cmd/vidai/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ func newGenerateCommand() *ffcli.Command {
114114
return fmt.Errorf("image or text is required")
115115
}
116116
c := vidai.New(&cfg)
117-
u, err := c.Generate(ctx, *image, *text, *output, *extend,
117+
id, u, err := c.Generate(ctx, *image, *text, *output, *extend,
118118
*interpolate, *upscale, *watermark)
119119
if err != nil {
120120
return err
121121
}
122-
fmt.Printf("Video URL: %s\n", u)
122+
fmt.Printf("ID: %s URL: %s\n", id, u)
123123
return nil
124124
},
125125
}

pkg/runway/runway.go

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -241,13 +241,16 @@ type artifact struct {
241241
ID string `json:"id"`
242242
CreatedAt string `json:"createdAt"`
243243
UpdatedAt string `json:"updatedAt"`
244+
Name string `json:"name"`
245+
MediaType string `json:"mediaType"`
244246
UserID int `json:"userId"`
245247
CreatedBy int `json:"createdBy"`
246248
TaskID string `json:"taskId"`
247249
ParentAssetGroupId string `json:"parentAssetGroupId"`
248250
Filename string `json:"filename"`
249251
URL string `json:"url"`
250-
FileSize string `json:"fileSize"`
252+
FileSize any `json:"fileSize"`
253+
FileExtension string `json:"fileExtStandardized"`
251254
IsDirectory bool `json:"isDirectory"`
252255
PreviewURLs []string `json:"previewUrls"`
253256
Private bool `json:"private"`
@@ -261,10 +264,10 @@ type artifact struct {
261264
} `json:"metadata"`
262265
}
263266

264-
func (c *Client) Generate(ctx context.Context, assetURL, textPrompt string, interpolate, upscale, watermark, extend bool) (string, error) {
267+
func (c *Client) Generate(ctx context.Context, assetURL, textPrompt string, interpolate, upscale, watermark, extend bool) (string, string, error) {
265268
// Load team ID
266269
if err := c.loadTeamID(ctx); err != nil {
267-
return "", fmt.Errorf("runway: couldn't load team id: %w", err)
270+
return "", "", fmt.Errorf("runway: couldn't load team id: %w", err)
268271
}
269272

270273
// Generate seed
@@ -311,35 +314,36 @@ func (c *Client) Generate(ctx context.Context, assetURL, textPrompt string, inte
311314
}
312315
var taskResp taskResponse
313316
if err := c.do(ctx, "POST", "tasks", createReq, &taskResp); err != nil {
314-
return "", fmt.Errorf("runway: couldn't create task: %w", err)
317+
return "", "", fmt.Errorf("runway: couldn't create task: %w", err)
315318
}
316319

317320
// Wait for task to finish
318321
for {
319322
switch taskResp.Task.Status {
320323
case "SUCCEEDED":
321324
if len(taskResp.Task.Artifacts) == 0 {
322-
return "", fmt.Errorf("runway: no artifacts returned")
325+
return "", "", fmt.Errorf("runway: no artifacts returned")
323326
}
324-
if taskResp.Task.Artifacts[0].URL == "" {
325-
return "", fmt.Errorf("runway: empty artifact url")
327+
artifact := taskResp.Task.Artifacts[0]
328+
if artifact.URL == "" {
329+
return "", "", fmt.Errorf("runway: empty artifact url")
326330
}
327-
return taskResp.Task.Artifacts[0].URL, nil
331+
return artifact.ID, artifact.URL, nil
328332
case "PENDING", "RUNNING":
329333
c.log("runway: task %s: %s", taskResp.Task.ID, taskResp.Task.ProgressRatio)
330334
default:
331-
return "", fmt.Errorf("runway: task failed: %s", taskResp.Task.Status)
335+
return "", "", fmt.Errorf("runway: task failed: %s", taskResp.Task.Status)
332336
}
333337

334338
select {
335339
case <-ctx.Done():
336-
return "", fmt.Errorf("runway: %w", ctx.Err())
340+
return "", "", fmt.Errorf("runway: %w", ctx.Err())
337341
case <-time.After(5 * time.Second):
338342
}
339343

340344
path := fmt.Sprintf("tasks/%s?asTeamId=%d", taskResp.Task.ID, c.teamID)
341345
if err := c.do(ctx, "GET", path, nil, &taskResp); err != nil {
342-
return "", fmt.Errorf("runway: couldn't get task: %w", err)
346+
return "", "", fmt.Errorf("runway: couldn't get task: %w", err)
343347
}
344348
}
345349
}
@@ -351,7 +355,10 @@ type assetDeleteResponse struct {
351355
Success bool `json:"success"`
352356
}
353357

354-
// TODO: Delete asset by url instead
358+
type assetResponse struct {
359+
Asset artifact `json:"asset"`
360+
}
361+
355362
func (c *Client) DeleteAsset(ctx context.Context, id string) error {
356363
path := fmt.Sprintf("assets/%s", id)
357364
var resp assetDeleteResponse
@@ -364,6 +371,18 @@ func (c *Client) DeleteAsset(ctx context.Context, id string) error {
364371
return nil
365372
}
366373

374+
func (c *Client) GetAsset(ctx context.Context, id string) (string, error) {
375+
path := fmt.Sprintf("assets/%s", id)
376+
var resp assetResponse
377+
if err := c.do(ctx, "GET", path, nil, &resp); err != nil {
378+
return "", fmt.Errorf("runway: couldn't get asset %s: %w", id, err)
379+
}
380+
if resp.Asset.URL == "" {
381+
return "", fmt.Errorf("runway: empty asset url")
382+
}
383+
return resp.Asset.URL, nil
384+
}
385+
367386
func (c *Client) log(format string, args ...interface{}) {
368387
if c.debug {
369388
format += "\n"

vidai.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,30 @@ func New(cfg *Config) *Client {
4848

4949
// Generate generates a video from an image and a text prompt.
5050
func (c *Client) Generate(ctx context.Context, image, text, output string,
51-
extend int, interpolate, upscale, watermark bool) (string, error) {
51+
extend int, interpolate, upscale, watermark bool) (string, string, error) {
5252
b, err := os.ReadFile(image)
5353
if err != nil {
54-
return "", fmt.Errorf("vidai: couldn't read image: %w", err)
54+
return "", "", fmt.Errorf("vidai: couldn't read image: %w", err)
5555
}
5656
name := filepath.Base(image)
5757

5858
var imageURL string
5959
if image != "" {
6060
imageURL, err = c.client.Upload(ctx, name, b)
6161
if err != nil {
62-
return "", fmt.Errorf("vidai: couldn't upload image: %w", err)
62+
return "", "", fmt.Errorf("vidai: couldn't upload image: %w", err)
6363
}
6464
}
65-
videoURL, err := c.client.Generate(ctx, imageURL, text, interpolate, upscale, watermark, false)
65+
id, videoURL, err := c.client.Generate(ctx, imageURL, text, interpolate, upscale, watermark, false)
6666
if err != nil {
67-
return "", fmt.Errorf("vidai: couldn't generate video: %w", err)
67+
return "", "", fmt.Errorf("vidai: couldn't generate video: %w", err)
6868
}
6969

7070
// Extend video
7171
for i := 0; i < extend; i++ {
72-
videoURL, err = c.client.Generate(ctx, videoURL, "", interpolate, upscale, watermark, true)
72+
id, videoURL, err = c.client.Generate(ctx, videoURL, "", interpolate, upscale, watermark, true)
7373
if err != nil {
74-
return "", fmt.Errorf("vidai: couldn't extend video: %w", err)
74+
return "", "", fmt.Errorf("vidai: couldn't extend video: %w", err)
7575
}
7676
}
7777

@@ -85,11 +85,11 @@ func (c *Client) Generate(ctx context.Context, image, text, output string,
8585
// Download video
8686
if videoPath != "" {
8787
if err := c.download(ctx, videoURL, videoPath); err != nil {
88-
return "", fmt.Errorf("vidai: couldn't download video: %w", err)
88+
return "", "", fmt.Errorf("vidai: couldn't download video: %w", err)
8989
}
9090
}
9191

92-
return videoURL, nil
92+
return id, videoURL, nil
9393
}
9494

9595
// Extend extends a video using the previous video.
@@ -131,7 +131,7 @@ func (c *Client) Extend(ctx context.Context, input, output string, n int,
131131
if err != nil {
132132
return nil, fmt.Errorf("vidai: couldn't upload image: %w", err)
133133
}
134-
videoURL, err := c.client.Generate(ctx, imageURL, "", interpolate, upscale, watermark, false)
134+
_, videoURL, err := c.client.Generate(ctx, imageURL, "", interpolate, upscale, watermark, false)
135135
if err != nil {
136136
return nil, fmt.Errorf("vidai: couldn't generate video: %w", err)
137137
}
@@ -184,6 +184,11 @@ func (c *Client) Extend(ctx context.Context, input, output string, n int,
184184
return urls, nil
185185
}
186186

187+
// URL returns the URL of a video.
188+
func (c *Client) URL(ctx context.Context, id string) (string, error) {
189+
return c.client.GetAsset(ctx, id)
190+
}
191+
187192
func (c *Client) download(ctx context.Context, url, output string) error {
188193
// Create request
189194
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)

0 commit comments

Comments
 (0)