Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add 7.1.4 and refactor a bit #9

Merged
merged 1 commit into from
Nov 7, 2024
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
18 changes: 0 additions & 18 deletions cmd/soundscape-sync/main.go

This file was deleted.

12 changes: 12 additions & 0 deletions internal/logic/sync-5.1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package logic

func get5_1Arguments() []string {
return []string{
// best audio format so far on ios
"-filter_complex", "[1:a]apad[a2];[0:a][a2]amerge=inputs=2[out]",
"-c:a", "aac", "-b:a", "654k",
// mp4 output
// "-filter_complex", "[1:a]apad[a2];[0:a][a2]amerge=inputs=2,pan=5.1|c0=c0+c6|c1=c1+c7|c2=c2|c3=c3|c4=c4|c5=c5[out]",
// "-c:a", "eac3", "-ac", "6",
}
}
8 changes: 8 additions & 0 deletions internal/logic/sync-7.1.4.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package logic

func get7_1_4Arguments() []string {
return []string{
"-filter_complex",
"[1:a]apad[a2];[0:a][a2]amerge=inputs=2,pan=7.1.4|FL=c0+c12|FR=c1+c13|FC=c2|LFE=c3|BL=c6|BR=c7|SL=c4|SR=c5|TFL=c8|TFR=c9|TBL=c10|TBR=c11[out]",
}
}
99 changes: 0 additions & 99 deletions internal/logic/sync-atmos.go

This file was deleted.

87 changes: 2 additions & 85 deletions internal/logic/sync-stereo.go
Original file line number Diff line number Diff line change
@@ -1,90 +1,7 @@
package logic

import (
"context"
"fmt"
"os/exec"
"path/filepath"

"fyne.io/fyne/v2/widget"
)

func combineStereoFiles(folder1 string, folder2 string, outputFolder string, progress *widget.ProgressBar) error {
// Get list of audio files from both folders
files1, err := getAudioFiles(folder1)
if err != nil {
return err
}
files2, err := getAudioFiles(folder2)
if err != nil {
return err
}

if len(files1) != len(files2) {
return fmt.Errorf("the number of audio files in the two folders must be the same")
}

ffmpegPath, err := getFFmpegPath()
if err != nil {
return err
}

total := len(files1)

for index, file := range files1 {
duration, err := getDuration(file)
if err != nil {
return err
}

// Construct FFmpeg command
ext := filepath.Ext(files2[index])
newFileName := outputFolder + "/" + filepath.Base(files2[index])
newFileName = newFileName[:len(newFileName)-4] + "_synced" + ext
ctx, _ := context.WithCancel(context.Background())
arguments := []string{
"-i", file,
"-i", files2[index],
func getStereoArguments() []string {
return []string{
"-filter_complex", "[1:a]apad[a2];[0:a][a2]amerge=inputs=2,pan=stereo|c0<c0+c2|c1<c1+c3[out]",
}
arguments = append(arguments, getBaseArguments()...)
arguments = append(arguments, getCoverArtArguments(file, files2[index])...)
arguments = append(arguments, newFileName)
cmd := exec.CommandContext(ctx, ffmpegPath, arguments...)
cmd.SysProcAttr = getSysProcAttr()
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}

// Execute FFmpeg command
if err := cmd.Start(); err != nil {
return err
}

parseProgress(index, total, progress, stdout, duration)

if err := cmd.Wait(); err != nil {
return err
}
}

cleanupTemp()

progress.SetValue(1.0)
return nil
}

func getCoverArtFromMp3 (filename string) error {
ffmpegPath, err := getFFmpegPath()
if err != nil {
return err
}

cmd := exec.Command(ffmpegPath, "-i", filename, "cover.jpg")
if err := cmd.Run(); err != nil {
return err
}

return nil
}
137 changes: 108 additions & 29 deletions internal/logic/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package logic
import (
"io"
"bufio"
"context"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -38,35 +39,101 @@ func getAudioFiles(folder string) ([]string, error) {
}

func CombineFiles(folder1 string, folder2 string, outputFolder string, progress *widget.ProgressBar) error {
ffprobe, err := getFFProbePath()
if err != nil {
return err
}
// ffmpeg probe if first audio file in folder 1 has more than 2 channel
audioFiles1, err := getAudioFiles(folder1)
if err != nil {
return err
}
if len(audioFiles1) == 0 {
return fmt.Errorf("no audio files found")
}
cmd := exec.Command(ffprobe, "-v", "error", "-select_streams", "a:0", "-count_packets", "-show_entries", "stream=channels", "-of", "csv=p=0", audioFiles1[0])
out, err := cmd.Output()
if err != nil {
return err
}
// out contains a pipe and another space character at the end, so we need to trim it
channels, err := strconv.Atoi(strings.TrimSuffix(strings.TrimSpace(string(out)), ","))
if err != nil {
return err
}
if channels == 2 {
return combineStereoFiles(folder1, folder2, outputFolder, progress)
}
if channels == 6 {
return combineAtmosFiles(folder1, folder2, outputFolder, progress)
}
return fmt.Errorf("Currently only stereo and 5.1 Soundscapes are supported", channels)
// Get list of audio files from both folders
files1, err := getAudioFiles(folder1)
if err != nil {
return err
}
files2, err := getAudioFiles(folder2)
if err != nil {
return err
}

if len(files1) != len(files2) {
return fmt.Errorf("the number of audio files in the two folders must be the same")
}

ffmpeg, err := getFFmpegPath()
if err != nil {
return err
}

total := len(files1)

for index, file := range files1 {
channel , err := getChannelAmount(file)
if err != nil {
return err
}
duration, err := getDuration(file)
if err != nil {
return err
}

channelArguments, err := getChannelArguments(channel)
if err != nil {
return err
}

// Get output file name
ext := filepath.Ext(file)
newFileName := outputFolder + "/" + filepath.Base(files2[index])
newFileName = newFileName[:len(newFileName)-4] + "_synced" + ext

// Construct FFmpeg command
ctx, _ := context.WithCancel(context.Background())
arguments := []string{
"-i", file,
"-i", files2[index],
}
arguments = append(arguments, channelArguments...)
arguments = append(arguments, getBaseArguments()...)
arguments = append(arguments, getCoverArtArguments(file, files2[index])...)
arguments = append(arguments, newFileName)
cmd := exec.CommandContext(ctx, ffmpeg, arguments...)
cmd.SysProcAttr = getSysProcAttr()
stdout, err := cmd.StdoutPipe()
if err != nil {
// prepend error with text
err = fmt.Errorf("error creating ffmpeg command: %w", err)
return err
}

// Execute FFmpeg command
if err := cmd.Start(); err != nil {
err = fmt.Errorf("error at ffmpeg command start: %w", err)
return err
}

parseProgress(index, total, progress, stdout, duration)

if err := cmd.Wait(); err != nil {
err = fmt.Errorf("error at ffmpeg command wait: %w", err)
return err
}
}

cleanupTemp()

return nil
}

func getChannelAmount(file string) (int, error) {
ffprobe, err := getFFProbePath()
if err != nil {
return 0, err
}

cmd := exec.Command(ffprobe, "-v", "error", "-select_streams", "a:0", "-count_packets", "-show_entries", "stream=channels", "-of", "csv=p=0", file)
out, err := cmd.Output()
if err != nil {
return 0, err
}
channels, err := strconv.Atoi(strings.TrimSuffix(strings.TrimSpace(string(out)), ","))
if err != nil {
return 0, err
}
return channels, nil
}

func getDuration(filename string) (float64, error) {
Expand Down Expand Up @@ -105,6 +172,18 @@ func getBaseArguments() []string {
}
}

func getChannelArguments(channels int) ([]string, error) {
switch channels {
case 2:
return getStereoArguments(), nil
case 6:
return get5_1Arguments(), nil
case 12:
return get7_1_4Arguments(), nil
}
return nil, fmt.Errorf("Currently only stereo, 5.1 and 7.1.4 Soundscapes are supported")
}

func getCoverArtArguments(file1 string, file2 string) []string {
arguments := []string{}
if testCoverArt(file1) {
Expand Down