Compare commits

...

5 Commits

5 changed files with 186 additions and 38 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__/

11
Taskfile.yml Normal file
View File

@ -0,0 +1,11 @@
# https://taskfile.dev
version: '3'
vars:
GREETING: Hello, World!
tasks:
format:
cmds:
- docker run --rm --volume $(pwd):/src --workdir /src pyfound/black:25.1.0 black .

34
convert_file_encoding.py Normal file
View File

@ -0,0 +1,34 @@
import os
import sys
def convert_encoding(filepath):
try:
with open(filepath, "r", encoding="cp1251", errors="strict") as f:
content = f.read()
with open(filepath, "w", encoding="utf-8", errors="strict") as f:
f.write(content)
print(f"Success: {filepath}")
except UnicodeDecodeError:
print(f"Error: {filepath} - not cp1251 encoded")
except Exception as e:
print(f"Error: {filepath} - {str(e)}")
def process_directory(root_dir):
if not os.path.isdir(root_dir):
print(f"Error: '{root_dir}' is not a valid directory")
sys.exit(1)
for root, _, files in os.walk(root_dir):
for file in files:
if file.endswith((".cue", ".log")):
file_path = os.path.join(root, file)
convert_encoding(file_path)
def execute(args):
process_directory(args.directory)

View File

@ -1,46 +1,39 @@
#!/usr/bin/env python3
import os
import sys
import argparse
import convert_file_encoding
import split_flac
def convert_encoding(filepath):
try:
with open(filepath, 'r', encoding='cp1251', errors='strict') as f:
content = f.read()
with open(filepath, 'w', encoding='utf-8', errors='strict') as f:
f.write(content)
print(f"Success: {filepath}")
except UnicodeDecodeError:
print(f"Error: {filepath} - not cp1251 encoded")
except Exception as e:
print(f"Error: {filepath} - {str(e)}")
def process_directory(root_dir):
for root, _, files in os.walk(root_dir):
for file in files:
if file.endswith(('.cue', '.log')):
file_path = os.path.join(root, file)
convert_encoding(file_path)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Recursively convert .cue and .log files from cp1251 to utf-8',
epilog='Example: python convert_encoding.py /path/to/directory'
def create_convert_parser(subparsers):
parser = subparsers.add_parser(
"convert",
description="Recursively convert .cue and .log files from cp1251 to utf-8",
epilog="Example: python convert_encoding.py /path/to/directory",
)
parser.add_argument(
'directory',
type=str,
help='Path to target directory for conversion'
"directory", type=str, help="Path to target directory for conversion"
)
args = parser.parse_args()
if not os.path.isdir(args.directory):
print(f"Error: '{args.directory}' is not a valid directory")
sys.exit(1)
process_directory(args.directory)
parser.set_defaults(func=convert_file_encoding.execute)
def create_split_parser(subparsers):
parser = subparsers.add_parser(
"split",
description="Разделение FLAC-файла по CUE с переносом оригинала во временную директорию",
)
parser.add_argument(
"directory", type=str, help="Path to target directory with flac and cue files"
)
parser.set_defaults(func=split_flac.execute)
if __name__ == "__main__":
top_parser = argparse.ArgumentParser()
subparsers = top_parser.add_subparsers()
create_convert_parser(subparsers)
create_split_parser(subparsers)
args = top_parser.parse_args()
print(args)
args.func(args)

109
split_flac.py Normal file
View File

@ -0,0 +1,109 @@
import argparse
import os
import shutil
import subprocess
import tempfile
import sys
def ensure_utils():
if not all(shutil.which(cmd) for cmd in ["shnsplit", "cuetag"]):
raise RuntimeError("Ошибка: Требуются shnsplit и cuetag")
def find_cue_file(directory):
cue_files = []
for f in os.listdir(directory):
if f.lower().endswith(".cue"):
cue_files.append(f)
if len(cue_files) != 1:
for f in cue_files:
print("Found CUE-file", f)
raise RuntimeError("Error: found multiple cue files")
return cue_files[0]
def find_flac_file(directory, cue_file):
cue_basename, _ = os.path.splitext(cue_file)
flac_file = cue_basename + ".flac"
if not os.path.exists(os.path.join(directory, flac_file)):
raise RuntimeError("Error: flac file not found", flac_file)
return flac_file
def process_directory(directory):
print("Search files in", directory)
cue_file = find_cue_file(directory)
print("CUE:", cue_file)
flac_file = find_flac_file(directory, cue_file)
print("FLAC:", flac_file)
flac_full_path = os.path.join(directory, flac_file)
# Создание временной директории
with tempfile.TemporaryDirectory(dir=directory) as tmp_dir:
try:
# Перенос оригинального FLAC во временную директорию
print("Move original FLAC file to", tmp_dir)
tmp_flac = os.path.join(tmp_dir, flac_file)
shutil.move(flac_full_path, tmp_flac)
# Выполнение разделения в исходной директории
print("Split FLAC-file...")
subprocess.run(
[
"shnsplit",
"-f",
cue_file,
"-o",
"flac",
"-t",
"%n - %t",
tmp_flac,
],
cwd=directory,
check=True,
)
# Добавление метаданных
print("Add tags from CUE-file...")
split_files = [f for f in os.listdir(directory) if f.endswith(".flac")]
if split_files:
subprocess.run(
["cuetag", cue_file] + split_files,
cwd=directory,
check=True,
)
except subprocess.CalledProcessError as e:
print(f"Error: {e}")
# Возврат оригинала при ошибке
shutil.move(tmp_flac, flac_full_path)
return
print("Done! File split and tagged")
def find_all_directories(root_dir):
"""Рекурсивный поиск всех поддиректорий в указанной директории"""
dir_list = []
for root, dirs, _ in os.walk(root_dir):
for dir_name in dirs:
if not dir_name.startswith("."):
full_path = os.path.join(root, dir_name)
dir_list.append(full_path)
return dir_list
def execute(args):
root_dir = args.directory
for d in find_all_directories(root_dir):
try:
process_directory(d)
except:
print("Failed", d)
print("Continue")
print()