tokenFactory/dto/openai_video.go

130 lines
4.3 KiB
Go

package dto
import (
"encoding/json"
"strconv"
"strings"
"time"
)
const (
VideoStatusUnknown = "unknown"
VideoStatusQueued = "queued"
VideoStatusInProgress = "in_progress"
VideoStatusCompleted = "completed"
VideoStatusFailed = "failed"
// ObjectVideoGeneration is the canonical object type for async video generation tasks.
ObjectVideoGeneration = "video.generation"
)
// OpenAIVideoOutput holds primary generation artifacts (industrial / OpenAI-style task contract).
type OpenAIVideoOutput struct {
VideoURL string `json:"video_url,omitempty"`
ThumbnailURL string `json:"thumbnail_url,omitempty"`
SrtURL string `json:"srt_url,omitempty"`
}
// OpenAIVideo is the unified response for POST submit and GET poll on /v1/videos/* (OpenAI-style video task API).
// Do not put the result URL in metadata; use Output.VideoURL only. Timestamps are RFC3339 in UTC.
type OpenAIVideo struct {
ID string `json:"id"`
Object string `json:"object"`
Model string `json:"model,omitempty"`
Status string `json:"status"`
Progress int `json:"progress"`
CreatedAt string `json:"created_at,omitempty"`
CompletedAt string `json:"completed_at,omitempty"`
Seconds string `json:"seconds,omitempty"`
Size string `json:"size,omitempty"`
RemixedFromVideoID string `json:"remixed_from_video_id,omitempty"`
Error *OpenAIVideoError `json:"error"`
Output *OpenAIVideoOutput `json:"output,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
// FormatTimeUnixRFC3339 converts a Unix second timestamp to RFC3339 (UTC), or returns "" if unset.
func FormatTimeUnixRFC3339(sec int64) string {
if sec <= 0 {
return ""
}
return time.Unix(sec, 0).UTC().Format(time.RFC3339)
}
func (m *OpenAIVideo) SetProgressStr(progress string) {
progress = strings.TrimSuffix(progress, "%")
m.Progress, _ = strconv.Atoi(progress)
}
// SetOutputVideoURL sets the primary video URL on Output (not metadata).
func (m *OpenAIVideo) SetOutputVideoURL(url string) {
url = strings.TrimSpace(url)
if url == "" {
return
}
if m.Output == nil {
m.Output = &OpenAIVideoOutput{}
}
m.Output.VideoURL = url
}
// SetMetadata sets supplemental key/values only. URL-like keys are routed to Output, not metadata.
func (m *OpenAIVideo) SetMetadata(k string, v any) {
if k == "url" || k == "video_url" {
if s, ok := v.(string); ok {
m.SetOutputVideoURL(s)
}
return
}
if m.Metadata == nil {
m.Metadata = make(map[string]any)
}
m.Metadata[k] = v
}
func NewOpenAIVideo() *OpenAIVideo {
return &OpenAIVideo{
Object: ObjectVideoGeneration,
Status: VideoStatusQueued,
}
}
type OpenAIVideoError struct {
Message string `json:"message"`
Code string `json:"code"`
}
// MarshalJSON encodes a null error explicitly as JSON null.
func (m OpenAIVideo) MarshalJSON() ([]byte, error) {
type alias struct {
ID string `json:"id"`
Object string `json:"object"`
Model string `json:"model,omitempty"`
Status string `json:"status"`
Progress int `json:"progress"`
CreatedAt string `json:"created_at,omitempty"`
CompletedAt string `json:"completed_at,omitempty"`
Seconds string `json:"seconds,omitempty"`
Size string `json:"size,omitempty"`
RemixedFromVideoID string `json:"remixed_from_video_id,omitempty"`
Error *OpenAIVideoError `json:"error"`
Output *OpenAIVideoOutput `json:"output,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
a := alias{
ID: m.ID,
Object: m.Object,
Model: m.Model,
Status: m.Status,
Progress: m.Progress,
CreatedAt: m.CreatedAt,
CompletedAt: m.CompletedAt,
Seconds: m.Seconds,
Size: m.Size,
RemixedFromVideoID: m.RemixedFromVideoID,
Error: m.Error,
Output: m.Output,
Metadata: m.Metadata,
}
return json.Marshal(a)
}