Initial commit
This commit is contained in:
commit
0ba0e82742
7 changed files with 449 additions and 0 deletions
6
config.toml
Normal file
6
config.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
OutputDir = "out/"
|
||||||
|
Channels = [ "https://www.youtube.com/@BudgetBuildsOfficial", "https://www.youtube.com/@RandomGaminginHD" ]
|
||||||
|
|
||||||
|
[YouTube]
|
||||||
|
VideoFormat = "bestvideo[height<=720]"
|
||||||
|
AudioFormat = "bestaudio"
|
29
ffmpeg.go
Normal file
29
ffmpeg.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
ffmpeg "github.com/u2takey/ffmpeg-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mergeStreams(path1 string, path2 string, output string) (err error) {
|
||||||
|
input := []*ffmpeg.Stream{ffmpeg.Input(path1), ffmpeg.Input(path2)}
|
||||||
|
|
||||||
|
defaultArgs := ffmpeg.KwArgs{"c:v": "copy", "c:a": "copy", "format": "matroska"}
|
||||||
|
|
||||||
|
var ffmpegLogLevel ffmpeg.KwArgs
|
||||||
|
var silent bool
|
||||||
|
|
||||||
|
if Flags.Verbose {
|
||||||
|
ffmpegLogLevel = ffmpeg.KwArgs{"v": "info"}
|
||||||
|
silent = false
|
||||||
|
} else if Flags.Quiet {
|
||||||
|
ffmpegLogLevel = ffmpeg.KwArgs{"v": "quiet"}
|
||||||
|
silent = true
|
||||||
|
} else {
|
||||||
|
ffmpegLogLevel = ffmpeg.KwArgs{"v": "error"}
|
||||||
|
silent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
kwArgs := ffmpeg.MergeKwArgs([]ffmpeg.KwArgs{ffmpegLogLevel, defaultArgs})
|
||||||
|
|
||||||
|
return ffmpeg.Output(input, output, kwArgs).OverWriteOutput().ErrorToStdOut().Silent(silent).Run()
|
||||||
|
}
|
23
file.go
Normal file
23
file.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
|
||||||
|
//"github.com/charmbracelet/log"
|
||||||
|
"github.com/h2non/filetype"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func getExtension(filePath string) (extension string, err error) {
|
||||||
|
buf, _ := os.ReadFile(filePath)
|
||||||
|
|
||||||
|
kind, _ := filetype.Match(buf)
|
||||||
|
if kind == filetype.Unknown {
|
||||||
|
return "", errors.New(fmt.Sprintf("Unknown file type."))
|
||||||
|
}
|
||||||
|
|
||||||
|
return kind.Extension, nil
|
||||||
|
}
|
31
go.mod
Normal file
31
go.mod
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
module ytva
|
||||||
|
|
||||||
|
go 1.23.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/BurntSushi/toml v1.4.0
|
||||||
|
github.com/alexflint/go-arg v1.5.1
|
||||||
|
github.com/charmbracelet/log v0.4.0
|
||||||
|
github.com/h2non/filetype v1.1.3
|
||||||
|
github.com/u2takey/ffmpeg-go v0.5.0
|
||||||
|
github.com/wader/goutubedl v0.0.0-20241224160441-33e26ae8181c
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/alexflint/go-scalar v1.2.0 // indirect
|
||||||
|
github.com/aws/aws-sdk-go v1.38.20 // indirect
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
|
github.com/charmbracelet/lipgloss v0.10.0 // indirect
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/muesli/reflow v0.3.0 // indirect
|
||||||
|
github.com/muesli/termenv v0.15.2 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/u2takey/go-utils v0.3.1 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||||
|
golang.org/x/net v0.33.0 // indirect
|
||||||
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
|
)
|
110
go.sum
Normal file
110
go.sum
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
|
github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y=
|
||||||
|
github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
|
||||||
|
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
||||||
|
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||||
|
github.com/aws/aws-sdk-go v1.38.20 h1:QbzNx/tdfATbdKfubBpkt84OM6oBkxQZRw6+bW2GyeA=
|
||||||
|
github.com/aws/aws-sdk-go v1.38.20/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
|
||||||
|
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
|
||||||
|
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
|
||||||
|
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
|
||||||
|
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||||
|
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||||
|
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||||
|
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||||
|
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||||
|
github.com/panjf2000/ants/v2 v2.4.2/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/u2takey/ffmpeg-go v0.5.0 h1:r7d86XuL7uLWJ5mzSeQ03uvjfIhiJYvsRAJFCW4uklU=
|
||||||
|
github.com/u2takey/ffmpeg-go v0.5.0/go.mod h1:ruZWkvC1FEiUNjmROowOAps3ZcWxEiOpFoHCvk97kGc=
|
||||||
|
github.com/u2takey/go-utils v0.3.1 h1:TaQTgmEZZeDHQFYfd+AdUT1cT4QJgJn/XVPELhHw4ys=
|
||||||
|
github.com/u2takey/go-utils v0.3.1/go.mod h1:6e+v5vEZ/6gu12w/DC2ixZdZtCrNokVxD0JUklcqdCs=
|
||||||
|
github.com/wader/goutubedl v0.0.0-20241224160441-33e26ae8181c h1:p1o/Deq8K9VL0f9ccabJtciMc3S8opTNgJ+2JP5cLZE=
|
||||||
|
github.com/wader/goutubedl v0.0.0-20241224160441-33e26ae8181c/go.mod h1:5KXd5tImdbmz4JoVhePtbIokCwAfEhUVVx3WLHmjYuw=
|
||||||
|
github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071 h1:QkrG4Zr5OVFuC9aaMPmFI0ibfhBZlAgtzDYWfu7tqQk=
|
||||||
|
github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071/go.mod h1:XD6emOFPHVzb0+qQpiNOdPL2XZ0SRUM0N5JHuq6OmXo=
|
||||||
|
gocv.io/x/gocv v0.25.0/go.mod h1:Rar2PS6DV+T4FL+PM535EImD/h13hGVaHhnCu1xarBs=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
113
youtube.go
Normal file
113
youtube.go
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"io"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
"github.com/wader/goutubedl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkURL(input string) (error) {
|
||||||
|
request, err := http.NewRequest("GET", input, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusNotFound {
|
||||||
|
return errors.New(fmt.Sprintf("Video does not exist!"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadVideo(url string, videoFormat string, audioFormat string, outDir string, sizeLimit float64) (err error) {
|
||||||
|
goutubedl.Path = "yt-dlp"
|
||||||
|
|
||||||
|
if err := checkURL(url); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("URL \"%s\" exists.", url)
|
||||||
|
|
||||||
|
video, err := goutubedl.New(context.Background(), url, goutubedl.Options{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := outDir+strconv.Itoa(int(video.Info.Timestamp))+" - "+video.Info.Title
|
||||||
|
|
||||||
|
if ! video.Info.IsLive {
|
||||||
|
/* VIDEO */
|
||||||
|
{
|
||||||
|
log.Debugf("Downloading video \"%s\" with format \"%s\"", video.Info.ID, videoFormat)
|
||||||
|
|
||||||
|
videoDLResult, err := video.Download(context.Background(), videoFormat)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer videoDLResult.Close()
|
||||||
|
|
||||||
|
file, err := os.OpenFile(path+"-vid", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
io.Copy(file, videoDLResult)
|
||||||
|
|
||||||
|
videoDLResult.Close()
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AUDIO */
|
||||||
|
{
|
||||||
|
log.Debugf("Downloading audio \"%s\" with format \"%s\"", video.Info.ID, audioFormat)
|
||||||
|
|
||||||
|
audioDLResult, err := video.Download(context.Background(), audioFormat)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer audioDLResult.Close()
|
||||||
|
|
||||||
|
file, err := os.OpenFile(path+"-audio", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
io.Copy(file, audioDLResult)
|
||||||
|
|
||||||
|
audioDLResult.Close()
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeStreams(path+"-vid",path+"-audio",path+".mkv")
|
||||||
|
|
||||||
|
if err := os.Remove(path+"-vid"); err != nil {
|
||||||
|
log.Warnf("Could not remove file \"%s\"", path+"-vid")
|
||||||
|
}
|
||||||
|
if err := os.Remove(path+"-audio"); err != nil {
|
||||||
|
log.Warnf("Could not remove file \"%s\"", path+"-audio")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
extension, err := getExtension(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Rename(path, path+"."+extension)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
137
ytva.go
Normal file
137
ytva.go
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"flag"
|
||||||
|
"context"
|
||||||
|
//"fmt"
|
||||||
|
"os"
|
||||||
|
//"io"
|
||||||
|
//"reflect"
|
||||||
|
|
||||||
|
//"google.golang.org/api/option"
|
||||||
|
//"google.golang.org/api/youtube/v3"
|
||||||
|
"github.com/wader/goutubedl"
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
"github.com/alexflint/go-arg"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type _flags struct {
|
||||||
|
Quiet bool `arg:"-q,--quiet" help:"Output only warnings and errors."`
|
||||||
|
Verbose bool `arg:"-v,--verbose" help:"Enables debug output."`
|
||||||
|
ConfigFile string `arg:"-c,--config,env:YTVA_CONFIG" help:"Specifies the path to a TOML formatted configuration file." default:"config.toml"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_flags) Description() string {
|
||||||
|
return "YouTube Video Archive - Downloads videos in bulk automatically"
|
||||||
|
}
|
||||||
|
|
||||||
|
var Flags _flags
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type ConfigFile struct {
|
||||||
|
OutputDir string
|
||||||
|
Channels []string
|
||||||
|
YouTube struct {
|
||||||
|
VideoFormat string
|
||||||
|
AudioFormat string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var MainConfig ConfigFile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_ = arg.MustParse(&Flags)
|
||||||
|
|
||||||
|
if Flags.Verbose {
|
||||||
|
log.SetReportCaller(true)
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
if Flags.Quiet {
|
||||||
|
log.Warn("Verbose and quiet specified. Defaulting to verbose.")
|
||||||
|
}
|
||||||
|
} else if Flags.Quiet {
|
||||||
|
log.SetLevel(log.WarnLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
confFile, err := os.ReadFile(Flags.ConfigFile)
|
||||||
|
if(err != nil) {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
confContent := string(confFile)
|
||||||
|
|
||||||
|
_, err = toml.Decode(confContent, &MainConfig)
|
||||||
|
|
||||||
|
log.Debug("", "config", MainConfig)
|
||||||
|
|
||||||
|
goutubedl.Path = "yt-dlp"
|
||||||
|
|
||||||
|
if _, err := os.Stat(MainConfig.OutputDir); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
if err := os.Mkdir(MainConfig.OutputDir, 0755); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, channel := range MainConfig.Channels {
|
||||||
|
log.Info("==========================================================================================================")
|
||||||
|
log.Infof("Channel URL: \"%s\"", channel)
|
||||||
|
|
||||||
|
optType := goutubedl.TypeFromString["channel"]
|
||||||
|
channel, err := goutubedl.New(context.Background(), channel,
|
||||||
|
goutubedl.Options{
|
||||||
|
Type: optType,
|
||||||
|
PlaylistEnd: 2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error creating YouTube service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Channel Name: %s", channel.Info.Channel)
|
||||||
|
|
||||||
|
basePath := MainConfig.OutputDir+"/"+channel.Info.Channel+"/"
|
||||||
|
|
||||||
|
if _, err := os.Stat(basePath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
if err := os.Mkdir(basePath, 0755); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range channel.Info.Entries {
|
||||||
|
log.Debugf("-----------------------------------------------------")
|
||||||
|
log.Debugf("Title: %s", v.Title)
|
||||||
|
log.Debugf("URL: %s", v.WebpageURL)
|
||||||
|
log.Debugf("Playlist: %s", v.Playlist)
|
||||||
|
log.Debugf("PublishedAt: %s", v.UploadDate)
|
||||||
|
log.Debugf("IsLive: %t", v.IsLive)
|
||||||
|
//log.Debugf("Description: %s\n", item.Snippet.Description)
|
||||||
|
|
||||||
|
dirPath := basePath+"/"+v.Playlist+"/"
|
||||||
|
if _, err := os.Stat(dirPath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
if err := os.Mkdir(dirPath, 0755); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Downloading video: %s", v.Title)
|
||||||
|
downloadVideo(v.WebpageURL, MainConfig.YouTube.VideoFormat, MainConfig.YouTube.AudioFormat, dirPath, 2^32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue