more customisation, more QoL improvements

an all-around good time!
This commit is contained in:
ari melody 2026-01-30 14:14:54 +00:00
parent 2954689784
commit 45db651388
Signed by: ari
GPG key ID: CF99829C92678188
9 changed files with 315 additions and 147 deletions

View file

@ -17,70 +17,59 @@ import (
"google.golang.org/api/youtube/v3"
)
var DEFAULT_TAGS = []string{
"ari melody",
"ari melody LIVE",
"livestream",
"vtuber",
"twitch",
"gaming",
"let's play",
"full VOD",
"VOD",
"stream",
"archive",
}
const (
CATEGORY_GAMING = "20"
CATEGORY_ENTERTAINMENT = "24"
YT_CATEGORY_GAMING = "20"
YT_CATEGORY_ENTERTAINMENT = "24"
)
type TitleType int
type CategoryType int
const (
TITLE_GAME TitleType = iota
TITLE_OTHER
CATEGORY_GAME CategoryType = iota
CATEGORY_ENTERTAINMENT
)
type (
Title struct {
Name string
Type TitleType
Url string
Category struct {
Name string
Type CategoryType
Url string
}
Video struct {
Title *Title
Part int
Date time.Time
Tags []string
Filename string
Title string
Category *Category
Part int
Date time.Time
Tags []string
Filename string
SizeBytes int64
}
)
func BuildVideo(metadata *scanner.Metadata) (*Video, error) {
var titleType TitleType
switch metadata.Category.Type {
case "gaming":
titleType = TITLE_GAME
default:
titleType = TITLE_OTHER
}
videoDate, err := time.Parse("2006-01-02", metadata.Date)
if err != nil {
return nil, fmt.Errorf("failed to parse date from metadata: %v", err)
}
return &Video{
Title: &Title{
var category *Category = nil
if metadata.Category != nil {
category = &Category{
Name: metadata.Category.Name,
Type: titleType,
Type: CATEGORY_ENTERTAINMENT,
Url: metadata.Category.Url,
},
}
var ok bool
category.Type, ok = videoCategoryStringTypes[metadata.Category.Type]
if !ok { category.Type = CATEGORY_ENTERTAINMENT }
}
return &Video{
Title: metadata.Title,
Category: category,
Part: metadata.Part,
Date: videoDate,
Tags: DEFAULT_TAGS,
Tags: DefaultTags,
Filename: path.Join(
metadata.FootageDir,
fmt.Sprintf(
@ -91,73 +80,92 @@ func BuildVideo(metadata *scanner.Metadata) (*Video, error) {
}
type (
MetaTitle struct {
MetaCategory struct {
Name string
Type string
Url string
}
Metadata struct {
Date string
Title *MetaTitle
Part int
Title string
Date string
Category *MetaCategory
Part int
}
)
var videoCategoryTypeStrings = map[CategoryType]string{
CATEGORY_GAME: "gaming",
CATEGORY_ENTERTAINMENT: "entertainment",
}
var videoCategoryStringTypes = map[string]CategoryType{
"gaming": CATEGORY_GAME,
"entertainment": CATEGORY_ENTERTAINMENT,
}
var videoYtCategory = map[CategoryType]string {
CATEGORY_GAME: YT_CATEGORY_GAMING,
CATEGORY_ENTERTAINMENT: YT_CATEGORY_ENTERTAINMENT,
}
var DefaultTags []string
func GetDefaultTags(filepath string) ([]string, error) {
file, err := os.ReadFile(filepath)
if err != nil { return nil, err }
tags := strings.Split(string(file), "\n")
return tags, nil
}
var titleTemplate *template.Template = template.Must(
template.ParseFiles("template/title.txt"),
)
func BuildTitle(video *Video) (string, error) {
var titleType string
switch video.Title.Type {
case TITLE_GAME:
titleType = "game"
case TITLE_OTHER:
fallthrough
default:
titleType = "other"
out := &bytes.Buffer{}
var category *MetaCategory
if video.Category != nil {
category = &MetaCategory{
Name: video.Category.Name,
Type: videoCategoryTypeStrings[video.Category.Type],
Url: video.Category.Url,
}
}
out := &bytes.Buffer{}
titleTemplate.Execute(out, Metadata{
// TODO: give templates date format and lowercase functions
// these should not be hard-coded!
err := titleTemplate.Execute(out, Metadata{
Title: video.Title,
Date: strings.ToLower(video.Date.Format("02 Jan 2006")),
Title: &MetaTitle{
Name: video.Title.Name,
Type: titleType,
Url: video.Title.Url,
},
Category: category,
Part: video.Part,
})
return strings.TrimSpace(out.String()), nil
return strings.TrimSpace(out.String()), err
}
var descriptionTemplate *template.Template = template.Must(
template.ParseFiles("template/description.txt"),
)
func BuildDescription(video *Video) (string, error) {
var titleType string
switch video.Title.Type {
case TITLE_GAME:
titleType = "game"
case TITLE_OTHER:
fallthrough
default:
titleType = "other"
out := &bytes.Buffer{}
var category *MetaCategory
if video.Category != nil {
category = &MetaCategory{
Name: video.Category.Name,
Type: videoCategoryTypeStrings[video.Category.Type],
Url: video.Category.Url,
}
}
out := &bytes.Buffer{}
descriptionTemplate.Execute(out, Metadata{
err := descriptionTemplate.Execute(out, Metadata{
Title: video.Title,
Date: strings.ToLower(video.Date.Format("02 Jan 2006")),
Title: &MetaTitle{
Name: video.Title.Name,
Type: titleType,
Url: video.Title.Url,
},
Category: category,
Part: video.Part,
})
return out.String(), nil
return strings.TrimSpace(out.String()), err
}
func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtube.Video, error) {
@ -182,12 +190,11 @@ func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtu
videoService := youtube.NewVideosService(service)
var categoryId string
switch video.Title.Type {
case TITLE_GAME:
categoryId = CATEGORY_GAMING
default:
categoryId = CATEGORY_ENTERTAINMENT
categoryId := YT_CATEGORY_ENTERTAINMENT
if video.Category != nil {
if cid, ok := videoYtCategory[video.Category.Type]; ok {
categoryId = cid
}
}
call := videoService.Insert([]string{
@ -196,7 +203,7 @@ func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtu
Snippet: &youtube.VideoSnippet{
Title: title,
Description: description,
Tags: append(DEFAULT_TAGS, video.Tags...),
Tags: append(DefaultTags, video.Tags...),
CategoryId: categoryId, // gaming
},
Status: &youtube.VideoStatus{
@ -213,6 +220,12 @@ func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtu
log.Println("Uploading video...")
call.ProgressUpdater(func(current, total int64) {
// for some reason, this only returns 0.
// instead, we pull the file size from the ffmpeg output directly.
if total == 0 { total = video.SizeBytes }
fmt.Printf("Uploading... (%.2f%%)\n", float64(current) / float64(total))
})
ytVideo, err := call.Do()
if err != nil {
log.Fatalf("Failed to upload video: %v\n", err)