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

Added docker image #88

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM python:slim-bookworm

# Install required packages
RUN apt update && apt install -y \
gcc \
g++ \
make \
ffmpeg \
&& rm -rf /var/lib/apt/lists/*

# Create app directory and copy project files
WORKDIR /app
COPY . /app/

# Build the SILK decoder
RUN cd ./silk && make && make decoder

ENTRYPOINT ["python","/app/converter.py"]
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,30 @@ sh converter.sh input ouput mp3

如果你需要在`Windows`下使用该程序,请下载[silk2mp3.exe](https://dl.kn007.net/directlink/silk2mp3.zip "silk2mp3.zip")应用程序来完成转换,你可<a href='/windows' target="_blank">点击这里</a>来查看更多Windows下如何使用的相关说明。


## Docker

Build docker image,

```
docker build -t soulmachine/silk-v3-decoder .
```

Convert a file:

```bash
docker run -it --rm -v /path/to/input/file:/input silk-v3-decoder /input/filename.slk mp3
```

Notice: the `33921FF3774A773BB193B6FD4AD7C33E.slk` is an audio file you need to convert, the `mp3` is a format you need to output.

Convert all audio files in a folder:

```bash
docker run -it --rm -v /path/to/input:/input -v /path/to/output:/output silk-v3-decoder /input /output mp3
```


## 其他说明

如果你需要对音频文件进行silk v3编码,源码也已经提供,并且对微信、QQ进行了兼容,详见参数。
Expand Down
124 changes: 124 additions & 0 deletions converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import os
import subprocess
from pathlib import Path
import argparse
import sys
import multiprocessing
from concurrent.futures import ProcessPoolExecutor
import logging

# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)

def convert_file(aud_file: str, mp3_file: str) -> bool:
"""
Convert a single .aud file to .mp3 format

Args:
aud_file: Path to input .aud file
mp3_file: Path to output .mp3 file

Returns:
bool: True if conversion successful, False otherwise
"""
pcm_path = aud_file + '.pcm'

try:
# Step 1: Convert .aud to .pcm using silk decoder
logging.info(f"Converting {aud_file} to PCM...")
decoder_result = subprocess.run(
['./silk/decoder', aud_file, pcm_path],
check=True,
capture_output=True,
text=True
)

# Verify PCM file was created successfully
if not os.path.exists(pcm_path):
logging.error(f"Error: PCM file {pcm_path} was not created")
return False

# Step 2: Convert .pcm to .mp3 using ffmpeg
os.makedirs(os.path.dirname(mp3_file), exist_ok=True)
logging.info(f"Converting {pcm_path} to MP3...")
ffmpeg_result = subprocess.run([
'ffmpeg',
'-y', # Overwrite output file if it exists
'-f', 's16le',
'-ar', '24000',
'-ac', '1',
'-i', pcm_path,
mp3_file
], check=True, capture_output=True, text=True)

# Step 3: Remove the intermediate .pcm file
os.remove(pcm_path)
# copy both creation and modification times from the .aud file to the .mp3 file
os.utime(mp3_file, (os.path.getatime(aud_file), os.path.getmtime(aud_file)))
logging.info(f"Successfully converted {aud_file} to {mp3_file}")
return True

except subprocess.CalledProcessError as e:
logging.error(f"Error converting {aud_file}: {e}")
if os.path.exists(pcm_path):
os.remove(pcm_path)
return False
except Exception as e:
logging.error(f"Unexpected error processing {aud_file}: {e}")
if os.path.exists(pcm_path):
os.remove(pcm_path)
return False

def process_task(task):
return convert_file(*task)

def convert_aud_to_mp3(input_dir: str, output_dir: str):
# Get all .aud files in the directory
aud_files = list(Path(input_dir).rglob('*.aud')) # Convert to list to get total count

total_count = len(aud_files)
success_count = 0

# Prepare conversion tasks
conversion_tasks = []
for aud_file in aud_files:
aud_path = str(aud_file)
# Get the relative path from input_dir
rel_path = os.path.relpath(aud_path, input_dir)
# Replace .aud extension with .mp3
mp3_rel_path = os.path.splitext(rel_path)[0] + '.mp3'
# Create full output path maintaining directory structure
mp3_path = os.path.join(output_dir, mp3_rel_path)
conversion_tasks.append((aud_path, mp3_path))

# Use ProcessPoolExecutor for parallel processing
max_workers = multiprocessing.cpu_count() # Use number of CPU cores
with ProcessPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(process_task, conversion_tasks))
success_count = sum(1 for result in results if result)

if total_count > 0:
logging.info(f"\nConversion complete: {success_count}/{total_count} files converted successfully")

if __name__ == "__main__":
# Set up logging configuration
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)

parser = argparse.ArgumentParser(description='Convert .aud files to .mp3 format')
parser.add_argument('input_dir', help='Directory containing .aud files')
parser.add_argument('output_dir', help='Directory for output .mp3 files')

args = parser.parse_args()

if not os.path.isdir(args.input_dir):
logging.error(f"Error: {args.input_dir} is not a valid directory")
sys.exit(1)

convert_aud_to_mp3(args.input_dir, args.output_dir)