generated from bing/readnotes
Compare commits
2 Commits
dc9d8b6e94
...
a724d602a5
Author | SHA1 | Date |
---|---|---|
|
a724d602a5 | |
|
9c3ee32098 |
|
@ -18,4 +18,6 @@
|
|||
.vscode
|
||||
*.log
|
||||
|
||||
go/bin
|
||||
go/bin
|
||||
|
||||
build/
|
||||
|
|
1
go.mod
1
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/bogem/id3v2/v2 v2.1.4
|
||||
github.com/coreos/go-oidc/v3 v3.1.0
|
||||
github.com/gin-gonic/gin v1.8.1
|
||||
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20241129212102-9c50ad6b591e
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/spf13/cobra v1.7.0
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
|
|
2
go.sum
2
go.sum
|
@ -198,6 +198,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
|
|||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20241129212102-9c50ad6b591e h1:8AnObPi8WmIgjwcidUxaREhXMSpyUJeeSrIkZTXdabw=
|
||||
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20241129212102-9c50ad6b591e/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(ogg2mp3)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
# 手动指定 Vorbis 和 MP3Lame 库的路径
|
||||
set(VORBIS_INCLUDE_DIRS /usr/include)
|
||||
set(VORBIS_LIBRARIES /usr/lib/x86_64-linux-gnu/libvorbisfile.so /usr/lib/x86_64-linux-gnu/libvorbis.so /usr/lib/x86_64-linux-gnu/libogg.so)
|
||||
set(MP3LAME_INCLUDE_DIRS /usr/include)
|
||||
set(MP3LAME_LIBRARIES /usr/lib/x86_64-linux-gnu/libmp3lame.so)
|
||||
|
||||
# 包含头文件目录
|
||||
include_directories(${VORBIS_INCLUDE_DIRS})
|
||||
include_directories(${MP3LAME_INCLUDE_DIRS})
|
||||
|
||||
# 添加源文件
|
||||
set(SOURCES ogg2mp3.cpp)
|
||||
|
||||
# 创建静态库
|
||||
add_library(ogg2mp3 STATIC ${SOURCES})
|
||||
|
||||
# 链接库
|
||||
target_link_libraries(ogg2mp3 ${VORBIS_LIBRARIES} ${MP3LAME_LIBRARIES})
|
|
@ -0,0 +1,97 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -L${SRCDIR}/build -logg2mp3 -lvorbisfile -lvorbis -logg -lmp3lame -lstdc++
|
||||
#include <stdlib.h>
|
||||
#include "ogg2mp3.h"
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
_ "github.com/ianlancetaylor/cgosymbolizer" // cgo 错误跟踪
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func convertOggToMp3(src string, dst string) C.int {
|
||||
input := C.CString(src)
|
||||
defer C.free(unsafe.Pointer(input))
|
||||
output := C.CString(dst)
|
||||
defer C.free(unsafe.Pointer(output))
|
||||
return C.convertOggToMp3(input, output)
|
||||
}
|
||||
// listOggFiles 遍历指定文件夹,返回所有 OGG 文件的路径列表
|
||||
func listOggFiles(dir string) ([]string, error) {
|
||||
var oggFiles []string
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".ogg") {
|
||||
oggFiles= append(oggFiles, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return oggFiles, err
|
||||
}
|
||||
|
||||
// convertOggFilesToMp3 将指定文件夹下的所有 OGG 文件转换为 MP3
|
||||
func convertOggFilesToMp3(files []string, outputDir string) {
|
||||
for _, file := range files {
|
||||
outputFile := filepath.Join(outputDir, strings.TrimSuffix(filepath.Base(file), ".ogg")+".mp3")
|
||||
if n := convertOggToMp3(file, outputFile); n != 0 {
|
||||
log.Printf("Error converting %s to %s: %d", file, outputFile, n)
|
||||
} else {
|
||||
log.Printf("Successfully converted %s to %s", file, outputFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
var rootCmd = &cobra.Command{Use: "main"}
|
||||
var convertCmd = &cobra.Command{
|
||||
Use: "file [input.ogg] [output.mp3]",
|
||||
Short: "Convert OGG to MP3",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
input := C.CString(args[0])
|
||||
defer C.free(unsafe.Pointer(input))
|
||||
output := C.CString(args[1])
|
||||
defer C.free(unsafe.Pointer(output))
|
||||
if n := C.convertOggToMp3(input, output); n != 0 {
|
||||
log.Fatalf("Error converting OGG to MP3: %d", n)
|
||||
}
|
||||
},
|
||||
}
|
||||
var convertDirCmd = &cobra.Command{
|
||||
Use: "dir [inputDir] [outputDir]",
|
||||
Short: "Convert all OGG files in a directory to MP3",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
inputDir := args[0]
|
||||
outputDir := inputDir + "_mp3"
|
||||
if len(args) == 2 {
|
||||
outputDir = args[1]
|
||||
}
|
||||
if _, err := os.Stat(outputDir); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
log.Fatalf("Error creating output directory: %v", err)
|
||||
}
|
||||
}
|
||||
oggFiles, err := listOggFiles(inputDir)
|
||||
if err != nil {
|
||||
log.Fatalf("Error listing OGG files: %v", err)
|
||||
}
|
||||
|
||||
convertOggFilesToMp3(oggFiles, outputDir)
|
||||
},
|
||||
}
|
||||
|
||||
rootCmd.AddCommand(convertCmd, convertDirCmd)
|
||||
rootCmd.Execute()
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#include <lame/lame.h>
|
||||
#include "ogg2mp3.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OGG_FILE_ERROR 1
|
||||
#define MP3_FILE_ERROR 2
|
||||
#define OGG_DECODE_ERROR 3
|
||||
#define MP3_ENCODE_ERROR 4
|
||||
|
||||
int convertOggToMp3(const char* oggFilePath, const char* mp3FilePath) {
|
||||
// 打开 OGG 文件
|
||||
FILE* oggFile = fopen(oggFilePath, "rb");
|
||||
if (!oggFile) {
|
||||
return OGG_FILE_ERROR;
|
||||
}
|
||||
|
||||
// 打开 MP3 文件
|
||||
FILE* mp3File = fopen(mp3FilePath, "wb");
|
||||
if (!mp3File) {
|
||||
fclose(oggFile);
|
||||
return MP3_FILE_ERROR;
|
||||
}
|
||||
|
||||
// 初始化 OGG 解码器
|
||||
OggVorbis_File vf;
|
||||
if (ov_open(oggFile, &vf, NULL, 0) < 0) {
|
||||
fclose(oggFile);
|
||||
fclose(mp3File);
|
||||
return OGG_DECODE_ERROR;
|
||||
}
|
||||
|
||||
// 获取音频信息
|
||||
vorbis_info* vi = ov_info(&vf, -1);
|
||||
|
||||
// 初始化 LAME 编码器
|
||||
lame_t lame = lame_init();
|
||||
lame_set_in_samplerate(lame, vi->rate);
|
||||
lame_set_num_channels(lame, vi->channels);
|
||||
lame_set_VBR(lame, vbr_default);
|
||||
lame_init_params(lame);
|
||||
|
||||
// 缓冲区
|
||||
const int BUFFER_SIZE = 4096;
|
||||
short int pcm_buffer[BUFFER_SIZE * vi->channels];
|
||||
unsigned char mp3_buffer[BUFFER_SIZE];
|
||||
|
||||
int read, write;
|
||||
int current_section;
|
||||
|
||||
// 读取 OGG 数据并编码为 MP3
|
||||
while ((read = ov_read(&vf, (char*)pcm_buffer, sizeof(pcm_buffer), 0, 2, 1, ¤t_section)) > 0) {
|
||||
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read / (2 * vi->channels), mp3_buffer, BUFFER_SIZE);
|
||||
fwrite(mp3_buffer, write, 1, mp3File);
|
||||
}
|
||||
|
||||
// 结束编码
|
||||
write = lame_encode_flush(lame, mp3_buffer, BUFFER_SIZE);
|
||||
fwrite(mp3_buffer, write, 1, mp3File);
|
||||
|
||||
// 清理
|
||||
lame_close(lame);
|
||||
ov_clear(&vf);
|
||||
fclose(mp3File);
|
||||
// fclose(oggFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int convertOggToMp3(const char* oggFilePath, const char* mp3FilePath);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
BIN
go/uiweb/uiweb
BIN
go/uiweb/uiweb
Binary file not shown.
Loading…
Reference in New Issue