Skip to content

Commit

Permalink
Merge pull request #1242 from CuriouslyCory/main
Browse files Browse the repository at this point in the history
Adding youtube --metadata flag
  • Loading branch information
eugeis authored Jan 3, 2025
2 parents b07054a + 1629f36 commit f5d94bf
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 11 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ yt() {
}
```

This also creates a `yt` alias that allows you to use `yt https://www.youtube.com/watch?v=4b0iet22VIk` to get your transcripts.
This also creates a `yt` alias that allows you to use `yt https://www.youtube.com/watch?v=4b0iet22VIk` to get transcripts, comments, and metadata.

#### Save your files in markdown using aliases

Expand Down Expand Up @@ -323,6 +323,7 @@ Application Options:
-y, --youtube= YouTube video "URL" to grab transcript, comments from it and send to chat
--transcript Grab transcript from YouTube video and send to chat (it used per default).
--comments Grab comments from YouTube video and send to chat
--metadata Grab metadata from YouTube video and send to chat
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
-u, --scrape_url= Scrape website URL to markdown using Jina AI
-q, --scrape_question= Search question using Jina AI
Expand Down Expand Up @@ -474,24 +475,26 @@ alias pbpaste='xclip -selection clipboard -o'
## Web Interface

Fabric now includes a built-in web interface that provides a GUI alternative to the command-line interface and an out-of-the-box website for those who want to get started with web development or blogging.
You can use this app as a GUI interface for Fabric, a ready to go blog-site, or a website template for your own projects.
You can use this app as a GUI interface for Fabric, a ready to go blog-site, or a website template for your own projects.

The `web/src/lib/content` directory includes starter `.obsidian/` and `templates/` directories, allowing you to open up the `web/src/lib/content/` directory as an [Obsidian.md](https://obsidian.md) vault. You can place your posts in the posts directory when you're ready to publish.

The `web/src/lib/content` directory includes starter `.obsidian/` and `templates/` directories, allowing you to open up the `web/src/lib/content/` directory as an [Obsidian.md](https://obsidian.md) vault. You can place your posts in the posts directory when you're ready to publish.
### Installing

The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app. 
The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app.

_You will need to run fabric in a separate terminal with the `fabric --serve` command._
_You will need to run fabric in a separate terminal with the `fabric --serve` command._

**From the fabric project `web/` directory:**

```shell
npm run dev

## or ##

pnpm run dev

## or your equivalent
## or your equivalent
```

### Streamlit UI
Expand All @@ -507,10 +510,12 @@ streamlit run streamlit.py
```

The Streamlit UI provides a user-friendly interface for:

- Running and chaining patterns
- Managing pattern outputs
- Creating and editing patterns
- Analyzing pattern results

## Meta

> [!NOTE]
Expand Down
13 changes: 12 additions & 1 deletion cli/cli.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -286,7 +287,7 @@ func Cli(version string) (err error) {
func processYoutubeVideo(
flags *Flags, registry *core.PluginRegistry, videoId string) (message string, err error) {

if !flags.YouTubeComments || flags.YouTubeTranscript {
if (!flags.YouTubeComments && !flags.YouTubeMetadata) || flags.YouTubeTranscript {
var transcript string
var language = "en"
if flags.Language != "" || registry.Language.DefaultLanguage.Value != "" {
Expand All @@ -312,6 +313,16 @@ func processYoutubeVideo(

message = AppendMessage(message, commentsString)
}

if flags.YouTubeMetadata {
var metadata *youtube.VideoMetadata
if metadata, err = registry.YouTube.GrabMetadata(videoId); err != nil {
return
}
metadataJson, _ := json.MarshalIndent(metadata, "", " ")
message = AppendMessage(message, string(metadataJson))
}

return
}

Expand Down
3 changes: 2 additions & 1 deletion cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ type Flags struct {
ChangeDefaultModel bool `short:"d" long:"changeDefaultModel" description:"Change default model"`
YouTube string `short:"y" long:"youtube" description:"YouTube video or play list \"URL\" to grab transcript, comments from it and send to chat or print it put to the console and store it in the output file"`
YouTubePlaylist bool `long:"playlist" description:"Prefer playlist over video if both ids are present in the URL"`
YouTubeTranscript bool `long:"transcript" description:"Grab transcript from YouTube video and send to chat (it used per default)."`
YouTubeTranscript bool `long:"transcript" description:"Grab transcript from YouTube video and send to chat (it is used per default)."`
YouTubeComments bool `long:"comments" description:"Grab comments from YouTube video and send to chat"`
YouTubeMetadata bool `long:"metadata" description:"Output video metadata"`
Language string `short:"g" long:"language" description:"Specify the Language Code for the chat, e.g. -g=en -g=zh" default:""`
ScrapeURL string `short:"u" long:"scrape_url" description:"Scrape website URL to markdown using Jina AI"`
ScrapeQuestion string `short:"q" long:"scrape_question" description:"Search question using Jina AI"`
Expand Down
63 changes: 60 additions & 3 deletions plugins/tools/youtube/youtube.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ func (o *YouTube) Grab(url string, options *Options) (ret *VideoInfo, err error)

ret = &VideoInfo{}

if options.Metadata {
if ret.Metadata, err = o.GrabMetadata(videoId); err != nil {
err = fmt.Errorf("error getting video metadata: %v", err)
return
}
}

if options.Duration {
if ret.Duration, err = o.GrabDuration(videoId); err != nil {
err = fmt.Errorf("error parsing video duration: %v", err)
Expand Down Expand Up @@ -369,12 +376,61 @@ type Options struct {
Transcript bool
Comments bool
Lang string
Metadata bool
}

type VideoInfo struct {
Transcript string `json:"transcript"`
Duration int `json:"duration"`
Comments []string `json:"comments"`
Transcript string `json:"transcript"`
Duration int `json:"duration"`
Comments []string `json:"comments"`
Metadata *VideoMetadata `json:"metadata,omitempty"`
}

type VideoMetadata struct {
Id string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
PublishedAt string `json:"publishedAt"`
ChannelId string `json:"channelId"`
ChannelTitle string `json:"channelTitle"`
CategoryId string `json:"categoryId"`
Tags []string `json:"tags"`
ViewCount uint64 `json:"viewCount"`
LikeCount uint64 `json:"likeCount"`
}

func (o *YouTube) GrabMetadata(videoId string) (metadata *VideoMetadata, err error) {
if err = o.initService(); err != nil {
return
}

call := o.service.Videos.List([]string{"snippet", "statistics"}).Id(videoId)
var response *youtube.VideoListResponse
if response, err = call.Do(); err != nil {
return nil, fmt.Errorf("error getting video metadata: %v", err)
}

if len(response.Items) == 0 {
return nil, fmt.Errorf("no video found with ID: %s", videoId)
}

video := response.Items[0]
viewCount := video.Statistics.ViewCount
likeCount := video.Statistics.LikeCount

metadata = &VideoMetadata{
Id: video.Id,
Title: video.Snippet.Title,
Description: video.Snippet.Description,
PublishedAt: video.Snippet.PublishedAt,
ChannelId: video.Snippet.ChannelId,
ChannelTitle: video.Snippet.ChannelTitle,
CategoryId: video.Snippet.CategoryId,
Tags: video.Snippet.Tags,
ViewCount: viewCount,
LikeCount: likeCount,
}
return
}

func (o *YouTube) GrabByFlags() (ret *VideoInfo, err error) {
Expand All @@ -383,6 +439,7 @@ func (o *YouTube) GrabByFlags() (ret *VideoInfo, err error) {
flag.BoolVar(&options.Transcript, "transcript", false, "Output only the transcript")
flag.BoolVar(&options.Comments, "comments", false, "Output the comments on the video")
flag.StringVar(&options.Lang, "lang", "en", "Language for the transcript (default: English)")
flag.BoolVar(&options.Metadata, "metadata", false, "Output video metadata")
flag.Parse()

if flag.NArg() == 0 {
Expand Down

0 comments on commit f5d94bf

Please sign in to comment.