Skip to content

Commit

Permalink
Merge pull request #22 from vladaad/dev
Browse files Browse the repository at this point in the history
Release 1.0 - full rewrite
  • Loading branch information
vladaad authored Dec 14, 2023
2 parents 1cc6bb1 + f370209 commit cdc2c51
Show file tree
Hide file tree
Showing 47 changed files with 1,533 additions and 1,858 deletions.
37 changes: 15 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,37 @@

# DiscordCompressor

A small program in Go that efficiently compresses videos using ffmpeg.
A small program in Go that efficiently compresses videos using FFmpeg to a certain filesize.

## Dependencies

[FFmpeg](https://ffmpeg.org) including FFprobe

### Optional (needed for some settings options)

[qaac](https://github.com/nu774/qaac)
[fdkaac](https://github.com/nu774/fdkaac)
[FFmpeg](https://ffmpeg.org)

## Usage

`discordcompressor <arguments> <input video(s)>`

* `-o filename` - Sets the output filename, extension is automatically added
* `-focus string` - Sets the focus - for example, "framerate" or "resolution" (configured in settings.json)
* `-mixaudio` - Mixes all audio tracks into one
* `-normalize` - Normalizes audio volume
* `-noscale` - Disables FPS limiting and scaling (not recommended)
* `-reenc string` - Force re-encodes audio or video ("a", "v", "av")
* `-settings string` - Selects the settings file - for example, settings-test.json.
* `-forcescore 60` - Forces a specific benchmark score when generating settings. Higher = slower, but higher-quality
settings.
* `-size 8` - Sets the target size in MB
* `-subfind string` - Finds a certain string in subtitles and cuts according to it
* `-size 25` - Sets the target size in MB
* `-last 10` - Compresses the last x seconds of a video
* `-ss 15` - Sets the starting time like in ffmpeg
* `-t 10` - Sets the time to encode after the start of the file or `-ss`
* `-ss 15` - Sets the start time of the video in seconds
* `-t 10` - Sets the time to encode after the start of the file or `-ss` in seconds
* `-mixaudio` - Mixes all audio tracks into one
* `-normaudio` - Normalizes audio volume (use if the input video's audio is very quiet, loud or uneven)
* `-settings string` - Selects the settings file if you have multiple, or generates a new one with the chosen suffix.
* `-debug` - Shows extra information. Please use when reporting bugs, or if you're just curious.
* `-c:v` - Forces a certain video encoder, specified in settings.json
* `-c:a` - Forces a certain audio encoder, specified in settings.json
* `-f` - Forces a certain container, for example, `-f mkv` will output a .mkv file.

Settings and logs are located in %appdata%\vladaad\dc on Windows and /home/username/.config/vladaad/dc on other
platforms.
Please check the wiki to get tips on how to make discordcompressor even more efficient without a performance penalty, or much faster.
Settings and logs are located in %appdata%\vladaad\dc on Windows and ~/.config/vladaad/dc on Linux

## Compiling from source

You need [Go 1.16](https://golang.org/dl/) or newer

Afterwards run `go build` or `build.sh`. `build.sh` builds execs for both 64bit and 32bit and both Windows and Linux.
Afterwards, run `go build`

<!-- prettier-ignore-start -->
<!-- DO NOT REMOVE - contributor_list:start -->
Expand Down
10 changes: 0 additions & 10 deletions build.sh

This file was deleted.

42 changes: 42 additions & 0 deletions encoder/FPSCap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package encoder

import (
"github.com/vladaad/discordcompressor/settings"
"strconv"
)

func calculateFPS(video *settings.Vid) (*settings.FPS, bool) {
modified := false // This variable is for accurate detection if FPS was changed, float fuckery? was making -vf fps=25/1 when input was 25.0000
fps := new(settings.FPS)
fps.D, fps.N = video.Input.FPS.D, video.Input.FPS.N
for {
if float64(fps.N)/float64(fps.D) > float64(video.Output.Settings.MaxFPS)+1 { // allow for leniency
if settings.Encoding.HalveFPS {
fps.D *= 2
modified = true
} else {
fps.N = video.Output.Settings.MaxFPS
fps.D = 1
modified = true
break
}
} else {
break
}
}
return fps, modified
}

func fpsFilter(video *settings.Vid) string {
fps := video.Output.FPS
if video.Input.FPS != video.Output.FPS {
var str string
expr := strconv.Itoa(fps.N)
expr += "/"
expr += strconv.Itoa(fps.D)
str = "fps=" + expr
return str
} else {
return ""
}
}
68 changes: 31 additions & 37 deletions encoder/audio/audio.go
Original file line number Diff line number Diff line change
@@ -1,55 +1,49 @@
package audio

import (
"github.com/vladaad/discordcompressor/metadata"
"github.com/vladaad/discordcompressor/settings"
"log"
"os"
"sync"
)

func EncodeAudio(video *settings.Video) (outBitrate float64, outFilename string) {
// filename
outFilenameBase := video.UUID + "."
// normalize audio
lnParams := new(LoudnormParams)
if video.Input.AudioChannels > 2 {
video.Output.Audio.Normalize = true
}
if video.Output.Audio.Normalize {
dec := decodeAudio(video, lnParams)
lnParams = detectVolume(dec)
if isAudioSilent(lnParams) {
return 0.0, ""
}
func GenFilename(video *settings.Vid) string {
filename := video.UUID + "."
switch video.Output.AEncoder.Type {
case "ffmpeg":
filename += video.Output.Settings.Container
case "qaac", "fdkaac", "fhgaac":
filename += "m4a"
}
// start decoding
dec := decodeAudio(video, lnParams)
// encode
switch video.Output.Audio.Encoder.Type {
return filename
}
func EncodeAudio(video *settings.Vid, wg *sync.WaitGroup) *settings.Vid {
defer wg.Done()
dec := decodeAudio(video)
switch video.Output.AEncoder.Type {
case "ffmpeg":
outFilename = outFilenameBase + video.Output.Video.Encoder.Container
encFFmpeg(outFilename, video, dec)
case "qaac":
outFilename = outFilenameBase + "m4a"
encQaac(outFilename, video, dec)
encFFmpeg(video, dec)
case "fdkaac":
outFilename = outFilenameBase + "m4a"
encFDKaac(outFilename, video, dec)
default:
log.Println("Encoder type " + video.Output.Audio.Encoder.Type + " not found")
os.Exit(0)
encFDK(video, dec)
case "fhgaac":
encFHG(video, dec)
case "qaac":
encQaac(video, dec)
}
// bitrate
if !settings.DryRun {
return metadata.GetStats(outFilename, true).Bitrate, outFilename

if !settings.Encoding.FastMode {
video.Output.Bitrate.Audio = getBitrate(video)
video.Output.Bitrate.Video = video.Output.Bitrate.Total - video.Output.Bitrate.Audio
} else {
return video.Output.Audio.Bitrate, outFilename
log.Println("Audio encoding finished!")
}
return video
}

func isAudioSilent(params *LoudnormParams) bool {
if params.LRA == "-inf" || params.Thresh == "-inf" || params.IL == "-inf" || params.TP == "-inf" {
return true
func getBitrate(video *settings.Vid) int {
info, err := os.Stat(video.Output.AudioFile)
if err != nil {
panic("Failed to get audio bitrate")
}
return false
return int(float64(info.Size()*8) / video.Time.Duration)
}
77 changes: 0 additions & 77 deletions encoder/audio/decode.go

This file was deleted.

49 changes: 49 additions & 0 deletions encoder/audio/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package audio

import (
"github.com/vladaad/discordcompressor/metadata"
"github.com/vladaad/discordcompressor/settings"
"io"
"log"
"os/exec"
)

func decodeAudio(video *settings.Vid) io.ReadCloser {
var options []string

// input
options = append(options, "-loglevel", "warning", "-stats")
options = append(options, metadata.AppendTimes(video)...)
options = append(options, "-i", video.InFile)

options = append(options, "-map_metadata", "-1")
options = append(options, "-map_chapters", "-1")

// filters
filters, mapping := getFilters(video)
if filters != "" {
options = append(options, "-filter_complex", filters)
}
options = append(options, "-map", mapping)

// output format
options = append(options, "-c:a", "pcm_s32le")
if video.Input.AChannels > 2 {
options = append(options, "-ac", "2")
}

options = append(options, "-f", "wav", "-")

if settings.Debug {
log.Println(options)
}

cmd := exec.Command(settings.General.FFmpegExecutable, options...)
pipe, _ := cmd.StdoutPipe()
err := cmd.Start()
if err != nil {
panic(err)
}

return pipe
}
54 changes: 25 additions & 29 deletions encoder/audio/fdkaac.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,39 @@ import (
"strings"
)

func encFDKaac(outFilename string, video *settings.Video, input io.ReadCloser) {
func encFDK(video *settings.Vid, input io.ReadCloser) {
var options []string
encoderSettings := strings.Split(video.Output.Audio.Encoder.Options, " ")

// Encoding options
if video.Output.Audio.Encoder.UsesBitrate {
options = append(options, "-b", strconv.FormatFloat(video.Output.Audio.Bitrate, 'f', -1, 64))
}
if video.Output.Audio.Encoder.Options != "" {
options = append(options, encoderSettings...)
}
// Input & output options
encoderSettings := strings.Split(video.Output.AEncoder.Args, " ")
// input
options = append(options, "-")
options = append(options, "-o", outFilename)
// encoding
options = append(options, encoderSettings...)
if !video.Output.AEncoder.TVBR {
options = append(options, "-b", strconv.Itoa(video.Output.Bitrate.Audio))
}
// output
options = append(options, "-o", video.Output.AudioFile)

if settings.Debug || settings.DryRun {
if settings.Debug {
log.Println(options)
}

// Running
if !settings.DryRun {
cmd := exec.Command(settings.General.FDKaacExecutable, options...)
// running
cmd := exec.Command(settings.General.FDKaacExecutable, options...)

cmd.Stdin = input
cmd.Stdin = input

if settings.ShowStdOut {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}
if !settings.Encoding.FastMode {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}

err := cmd.Start()
if err != nil {
panic(err)
}
err = cmd.Wait()
if err != nil {
panic(err)
}
err := cmd.Start()
if err != nil {
panic(err)
}
err = cmd.Wait()
if err != nil {
panic(err)
}
}
Loading

0 comments on commit cdc2c51

Please sign in to comment.