Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 32 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,20 +122,38 @@ Video title, description etc can specified via the command line flags or via a J

```json
{
"title": "my test title",
"description": "my test description",
"tags": ["test tag1", "test tag2"],
"privacyStatus": "private",
"madeForKids": false,
"embeddable": true,
"license": "creativeCommon",
"publicStatsViewable": true,
"publishAt": "2017-06-01T12:05:00+02:00",
"categoryId": "10",
"recordingDate": "2017-05-21",
"playlistIds": ["xxxxxxxxxxxxxxxxxx", "yyyyyyyyyyyyyyyyyy"],
"playlistTitles": ["my test playlist"],
"language": "fr"
"title": "my test title",
"description": "my test description",
"tags": [
"test tag1",
"test tag2"
],
"privacyStatus": "private",
"madeForKids": false,
"embeddable": true,
"license": "creativeCommon",
"publicStatsViewable": true,
"publishAt": "2017-06-01T12:05:00+02:00",
"categoryId": "10",
"recordingDate": "2017-05-21",
"playlistIds": [
"xxxxxxxxxxxxxxxxxx",
"yyyyyyyyyyyyyyyyyy"
],
"playlistTitles": [
"my test playlist"
],
"language": "fr",
"localizations": {
"en": {
"title": "My English Title",
"description": "My English description"
},
"it": {
"title": "Il mio titolo in italiano",
"description": "La mia descrizione in italiano"
}
}
}
```
- all fields are optional
Expand Down
11 changes: 7 additions & 4 deletions files.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ type Date struct {
time.Time
}

func LoadVideoMeta(config Config, video *youtube.Video) (*VideoMeta, error) {
func LoadVideoMeta(config Config) (*VideoMeta, *youtube.Video, error) {
videoMeta := &VideoMeta{}
video := &youtube.Video{}

video.Snippet = &youtube.VideoSnippet{}
video.RecordingDetails = &youtube.VideoRecordingDetails{}
Expand All @@ -86,19 +87,21 @@ func LoadVideoMeta(config Config, video *youtube.Video) (*VideoMeta, error) {
file, e := os.ReadFile(config.MetaJSON)
if e != nil {
e2 := fmt.Errorf("error reading file %q: %w", config.MetaJSON, e)
return nil, e2
return nil, nil, e2
}

e = json.Unmarshal(file, &videoMeta)
if e != nil {
e2 := fmt.Errorf("error parsing file %q: %w", config.MetaJSON, e)
return nil, e2
return nil, nil, e2
}

video.Snippet.Tags = videoMeta.Tags
video.Snippet.Title = videoMeta.Title
video.Snippet.Description = videoMeta.Description
video.Snippet.CategoryId = videoMeta.CategoryId
video.Localizations = videoMeta.Localizations

// Location has been deprecated by Google
// see: https://developers.google.com/youtube/v3/revision_history#release_notes_06_01_2017
/*
Expand Down Expand Up @@ -185,7 +188,7 @@ func LoadVideoMeta(config Config, video *youtube.Video) (*VideoMeta, error) {
slices.Sort(playlistIDs)
videoMeta.PlaylistIDs = slices.Compact(playlistIDs)

return videoMeta, nil
return videoMeta, video, nil
}

func Open(filename string, mediaType MediaType) (io.ReadCloser, int64, error) {
Expand Down
2 changes: 2 additions & 0 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type VideoMeta struct {

// BCP-47 language code e.g. 'en','es'
Language string `json:"language,omitempty"`

Localizations map[string]youtube.VideoLocalization `json:"localizations,omitempty"`
}

func playlistList(service *youtube.Service, pageToken string) (*youtube.PlaylistListResponse, error) {
Expand Down
30 changes: 14 additions & 16 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@ func Run(ctx context.Context, transport *limiter.LimitTransport, config Config,
return fmt.Errorf("error building OAuth client: %w", err)
}

upload := &youtube.Video{}

videoMeta, err := LoadVideoMeta(config, upload)
videoMeta, uploadVideo, err := LoadVideoMeta(config)
if err != nil {
return fmt.Errorf("error loading video meta data: %w", err)
}
Expand All @@ -111,28 +109,28 @@ func Run(ctx context.Context, transport *limiter.LimitTransport, config Config,
}

var option googleapi.MediaOption
var video *youtube.Video
var resultVideo *youtube.Video

option = googleapi.ChunkSize(config.Chunksize)

call := service.Videos.Insert([]string{"snippet", "status", "recordingDetails"}, upload)
call := service.Videos.Insert([]string{"snippet", "status", "localizations", "recordingDetails"}, uploadVideo)
if config.SendFileName && config.Filename != "-" {
filetitle := filepath.Base(config.Filename)
slog.Debug("adding file name to request", "file", filetitle)
call.Header().Set("Slug", filetitle)
}
video, err = call.NotifySubscribers(config.NotifySubscribers).Media(videoReader, option).Do()
resultVideo, err = call.NotifySubscribers(config.NotifySubscribers).Media(videoReader, option).Do()
if err != nil {
if video != nil {
return fmt.Errorf("error making YouTube API call: %w, %v", err, video.HTTPStatusCode)
if resultVideo != nil {
return fmt.Errorf("error making YouTube API call: %w, %v", err, resultVideo.HTTPStatusCode)
} else {
return fmt.Errorf("error making YouTube API call: %w", err)
}
}
fmt.Printf("\nUpload successful! Video ID: %v\n", video.Id)
fmt.Printf("\nUpload successful! Video ID: %v\n", resultVideo.Id)

if config.MetaJSONOut != "" {
JSONOut, _ := json.Marshal(video)
JSONOut, _ := json.Marshal(resultVideo)
err = os.WriteFile(config.MetaJSONOut, JSONOut, 0666)
if err != nil {
return fmt.Errorf("error writing to video metadata file %q: %w", config.MetaJSONOut, err)
Expand All @@ -142,7 +140,7 @@ func Run(ctx context.Context, transport *limiter.LimitTransport, config Config,

if thumbReader != nil {
fmt.Printf("Uploading thumbnail %q...\n", config.Thumbnail)
_, err = service.Thumbnails.Set(video.Id).Media(thumbReader).Do()
_, err = service.Thumbnails.Set(resultVideo.Id).Media(thumbReader).Do()
if err != nil {
return fmt.Errorf("error making YouTube API call: %w", err)
}
Expand All @@ -154,7 +152,7 @@ func Run(ctx context.Context, transport *limiter.LimitTransport, config Config,
captionObj := &youtube.Caption{
Snippet: &youtube.CaptionSnippet{},
}
captionObj.Snippet.VideoId = video.Id
captionObj.Snippet.VideoId = resultVideo.Id
captionObj.Snippet.Language = config.Language
captionObj.Snippet.Name = config.Language
captionInsert := service.Captions.Insert([]string{"snippet"}, captionObj).Sync(true)
Expand All @@ -169,15 +167,15 @@ func Run(ctx context.Context, transport *limiter.LimitTransport, config Config,
}

plx := &Playlistx{}
if upload.Status.PrivacyStatus != "" {
plx.PrivacyStatus = upload.Status.PrivacyStatus
if uploadVideo.Status.PrivacyStatus != "" {
plx.PrivacyStatus = uploadVideo.Status.PrivacyStatus
}

if len(videoMeta.PlaylistIDs) > 0 {
plx.Title = ""
for _, pid := range videoMeta.PlaylistIDs {
plx.Id = pid
err = plx.AddVideoToPlaylist(service, video.Id)
err = plx.AddVideoToPlaylist(service, resultVideo.Id)
if err != nil {
return fmt.Errorf("error adding video to playlist: %w", err)
}
Expand All @@ -188,7 +186,7 @@ func Run(ctx context.Context, transport *limiter.LimitTransport, config Config,
plx.Id = ""
for _, title := range videoMeta.PlaylistTitles {
plx.Title = title
err = plx.AddVideoToPlaylist(service, video.Id)
err = plx.AddVideoToPlaylist(service, resultVideo.Id)
if err != nil {
return fmt.Errorf("error adding video to playlist: %w", err)
}
Expand Down
Loading