162 lines
4.5 KiB
Go
162 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const delaiDebut float64 = 2.00 //secondes
|
|
const delaiFin float64 = 0.20 //secondes
|
|
|
|
/* transforme la chaine de temps en ms
|
|
* format d'entrée : une chaine au format hh:mm:ss.ms (pas d'obligation d'avoir des heurs ou minutes )
|
|
*/
|
|
|
|
func strTimeToS(strTime string) (float64, error) {
|
|
tabTime := strings.Split(strTime, ":")
|
|
var (
|
|
timeMultiplicateur int = 1
|
|
time float64
|
|
)
|
|
for i := len(tabTime) - 1; i >= 0; i-- {
|
|
timeVal, err := strconv.ParseFloat(tabTime[i], 64)
|
|
if err != nil {
|
|
return 0, errors.New("format invalide, nombre incorrect")
|
|
}
|
|
time += float64(timeMultiplicateur) * timeVal
|
|
timeMultiplicateur *= 60
|
|
}
|
|
|
|
return time, nil
|
|
}
|
|
|
|
func GetInfo(ligne string) (float64, string, string, error) {
|
|
//split la ligne en 2 sur le premier espace
|
|
tabInfo := strings.SplitN(ligne, " ", 2)
|
|
strTime, strTitre := tabInfo[0], tabInfo[1]
|
|
|
|
debTime, err := strTimeToS(strTime)
|
|
if err != nil {
|
|
return 0, "", "", err
|
|
}
|
|
|
|
//split tmpTitre en artiste + titre en séparant par " - "
|
|
split := strings.SplitN(strTitre, " - ", 2)
|
|
var artiste, titre string
|
|
if len(split) > 1 {
|
|
artiste, titre = split[0], split[1]
|
|
} else {
|
|
titre = split[0]
|
|
}
|
|
return debTime, artiste, titre, nil
|
|
}
|
|
|
|
// on suppose un flux a 128kb/s soit 128000/8 kB/s
|
|
func timerToBytes(timer float64) int64 {
|
|
return int64(128000. / 8. * timer)
|
|
}
|
|
|
|
func isWriteMp3(filename string, newSize int64) bool {
|
|
fileInfo, err := os.Stat(filename)
|
|
// si le fichier n'existe pasn on peut ecrire le mp3
|
|
if os.IsNotExist(err) {
|
|
return true
|
|
}
|
|
// si le fichier existant est plus petit que le fichier qu'on souhaite créer, on l'ecrase
|
|
fileSize := fileInfo.Size()
|
|
return fileSize < newSize
|
|
}
|
|
|
|
func cutAndSave(mp3File string, timerDebut float64, timerFin float64, artiste string, titre string) {
|
|
octetDebut := timerToBytes(timerDebut)
|
|
octetsFin := timerToBytes(timerFin)
|
|
|
|
//fmt.Printf("je coupe le fichier %s de %v a %v le mp3 de %s s'apellant %s \n", mp3File, timerDebut, timerFin, artiste, titre)
|
|
|
|
// ouvrir le fichier
|
|
f, err := os.Open(mp3File)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Erreur d'ouverture du fichier mp3 : %v\n", err)
|
|
panic(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
bufferSize := octetsFin - octetDebut
|
|
|
|
// créer un tampon pour stocker les octets lus
|
|
tampon := make([]byte, bufferSize)
|
|
|
|
// lire les octets spécifiés à partir de la position spécifiée
|
|
n, err := f.ReadAt(tampon, int64(octetDebut))
|
|
// en cas d'erreur EOF, on continue comme si de rien n'était (il est possible qu'on tente
|
|
//d'accedeer un pu plus loin que la fin du fichier avec le delaiFin, ce n'est pas grave ça passera la fois d'apres )
|
|
if err != nil && !errors.Is(err, io.EOF) {
|
|
fmt.Fprintf(os.Stderr, "Erreur de lecture du fichier mp3 de %d a %d soit %d octets: %v\n", octetDebut, octetsFin, n, err)
|
|
panic(err)
|
|
}
|
|
|
|
// Écriture du tableau d'octets dans un fichier
|
|
artiste = strings.ReplaceAll(artiste, "/", "_")
|
|
if artiste == "" {
|
|
artiste = "Inconnu"
|
|
}
|
|
titre = strings.ReplaceAll(titre, "/", "_")
|
|
|
|
var outputFile string = fmt.Sprintf("%s.__.%s.mp3", artiste, titre)
|
|
if isWriteMp3(outputFile, bufferSize) {
|
|
err = os.WriteFile(outputFile, tampon, 0644)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Erreur d'écriture du fichier mp3 du morceau: %v\n", err)
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func Cut(mp3File string, indexFile string) {
|
|
// Ouvrir le fichier index en lecture
|
|
fichier, err := os.Open(indexFile)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Erreur d'ouverture du fichier index : %v\n", err)
|
|
panic(err)
|
|
}
|
|
defer fichier.Close()
|
|
|
|
// Créer un scanner pour lire le fichier ligne par ligne
|
|
scanner := bufio.NewScanner(fichier)
|
|
|
|
// Parcourir chaque ligne du fichier
|
|
timerPrecedent := -1.
|
|
artistePrecedent := ""
|
|
titrePrecedent := ""
|
|
for scanner.Scan() {
|
|
// Faire quelque chose avec la ligne, par exemple :
|
|
ligne := scanner.Text()
|
|
timer, artiste, titre, err := GetInfo(ligne)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Erreur de récupération des infos de la ligne %s : %v\n", ligne, err)
|
|
panic(err)
|
|
}
|
|
|
|
if timerPrecedent != -1. {
|
|
cutAndSave(mp3File, timerPrecedent-delaiDebut, timer+delaiFin, artistePrecedent, titrePrecedent)
|
|
timerPrecedent = timer
|
|
} else {
|
|
timerPrecedent = 0. + delaiDebut
|
|
}
|
|
artistePrecedent = artiste
|
|
titrePrecedent = titre
|
|
|
|
}
|
|
|
|
// Vérifier s'il y a eu une erreur lors de la lecture du fichier
|
|
if err := scanner.Err(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Erreur de lecture du fichier index : %v\n", err)
|
|
panic(err)
|
|
}
|
|
}
|