Skip to content

Commit e48c387

Browse files
committed
feat: allow no subtitles
1 parent f0a6412 commit e48c387

2 files changed

Lines changed: 25 additions & 15 deletions

File tree

buganime/buganime.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import json
1010
import subprocess
1111
import asyncio
12+
import argparse
1213
from typing import Iterator, Any
1314

1415
import win32event
@@ -44,7 +45,7 @@ class Movie:
4445
name: str
4546

4647

47-
def parse_streams(streams: Any) -> transcode.VideoInfo:
48+
def parse_streams(streams: Any, accept_no_subtitles: bool = False) -> transcode.VideoInfo:
4849
def _get_video_stream() -> Any:
4950
video_streams = [stream for stream in streams if stream['codec_type'] == 'video']
5051
if len(video_streams) == 1:
@@ -83,7 +84,13 @@ def _get_subtitle_stream_index() -> int:
8384
return max(relevant_streams, key=lambda x: int(x[1]['tags'].get('NUMBER_OF_BYTES-eng', '0')))[0]
8485

8586
video = _get_video_stream()
86-
return transcode.VideoInfo(audio_index=_get_audio_stream()['index'], subtitle_index=_get_subtitle_stream_index(),
87+
subtitle_index = None
88+
try:
89+
subtitle_index = _get_subtitle_stream_index()
90+
except RuntimeError:
91+
if not accept_no_subtitles:
92+
raise RuntimeError('No subtitles found')
93+
return transcode.VideoInfo(audio_index=_get_audio_stream()['index'], subtitle_index=subtitle_index,
8794
width=video['width'], height=video['height'], fps=video['r_frame_rate'],
8895
frames=int(video.get('tags', {}).get('NUMBER_OF_FRAMES') or video.get('tags', {}).get('NUMBER_OF_FRAMES-eng') or 0))
8996

@@ -122,7 +129,7 @@ def parse_filename(input_path: str) -> TVShow | Movie:
122129
return Movie(name=input_name)
123130

124131

125-
def process_file(input_path: str) -> None:
132+
def process_file(input_path: str, accept_no_subtitles: bool = False) -> None:
126133
if not input_path.endswith('.mkv'):
127134
return
128135

@@ -142,7 +149,7 @@ def process_file(input_path: str) -> None:
142149
proc = subprocess.run(['ffprobe', '-show_format', '-show_streams', '-of', 'json', input_path], text=True, capture_output=True, check=True,
143150
encoding='utf-8')
144151
logging.info('ffprobe %s wrote %s, %s', str(proc.args), proc.stderr, proc.stdout)
145-
video_info = parse_streams(json.loads(proc.stdout)['streams'])
152+
video_info = parse_streams(json.loads(proc.stdout)['streams'], accept_no_subtitles=accept_no_subtitles)
146153

147154
try:
148155
with lock_mutex(name=UPSCALE_MUTEX_NAME):
@@ -158,24 +165,25 @@ def process_file(input_path: str) -> None:
158165
raise
159166

160167

161-
def process_path(input_path: str) -> None:
168+
def process_path(input_path: str, accept_no_subtitles: bool = False) -> None:
162169
if os.path.isdir(input_path):
163170
for root, _, files in os.walk(input_path):
164171
for file in files:
165172
try:
166-
process_file(input_path=os.path.join(root, file))
173+
process_file(input_path=os.path.join(root, file), accept_no_subtitles=accept_no_subtitles)
167174
except Exception:
168175
logging.exception('Failed to convert %s', input_path)
169176
else:
170-
process_file(input_path=input_path)
177+
process_file(input_path=input_path, accept_no_subtitles=accept_no_subtitles)
171178

172179

173180
def main(args: list[str]) -> int:
174-
if len(args) != 1:
175-
print('Usage: buganime.py <input_path>')
176-
return 1
181+
argparser = argparse.ArgumentParser(description='Convert anime files to 4K')
182+
argparser.add_argument('input_path', type=str, help='Path to the input file or directory')
183+
argparser.add_argument('--accept-no-subtitles', action='store_true', help='Accept files with no subtitles')
184+
parsed = argparser.parse_args(args)
177185

178-
input_path = args[0]
186+
input_path = parsed.input_path
179187
log_prefix = f'buganime_{os.path.basename(input_path)}_{datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S")}'
180188
with tempfile.NamedTemporaryFile(mode='w', prefix=log_prefix, suffix='.txt', delete=False) as log_file:
181189
pass
@@ -193,7 +201,7 @@ def main(args: list[str]) -> int:
193201

194202
logging.info('Buganime started running on %s', input_path)
195203
try:
196-
process_path(input_path=input_path)
204+
process_path(input_path=input_path, accept_no_subtitles=parsed.accept_no_subtitles)
197205
return 0
198206
except Exception:
199207
logging.exception('Failed to convert %s', input_path)

buganime/transcode.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
@dataclass
2424
class VideoInfo:
2525
audio_index: int
26-
subtitle_index: int
26+
subtitle_index: Optional[int]
2727
width: int
2828
height: int
2929
fps: str
@@ -94,11 +94,13 @@ async def __write_output_frames(self, frames: AsyncIterator[bytes]) -> None:
9494
os.link(self.__input_path, os.path.join(temp_dir, 'input.mkv'))
9595
else:
9696
shutil.copy(self.__input_path, os.path.join(temp_dir, 'input.mkv'))
97+
filter = f'pad={self.__width_out}:{self.__height_out}:(ow-iw)/2:(oh-ih)/2:black'
98+
if self.__video_info.subtitle_index is not None:
99+
filter = f'subtitles=input.mkv:si={self.__video_info.subtitle_index}, {filter}'
97100
args = ('-f', 'rawvideo', '-framerate', str(self.__video_info.fps), '-pix_fmt', 'rgb24',
98101
'-s', f'{self.__upscale_width_out}x{self.__upscale_height_out}',
99102
'-i', 'pipe:', '-i', 'input.mkv',
100-
'-map', '0', '-map', f'1:{self.__video_info.audio_index}',
101-
'-vf', f'subtitles=input.mkv:si={self.__video_info.subtitle_index}, pad={self.__width_out}:{self.__height_out}:(ow-iw)/2:(oh-ih)/2:black',
103+
'-map', '0', '-map', f'1:{self.__video_info.audio_index}', '-vf', filter,
102104
*FFMPEG_OUTPUT_ARGS, self.__output_path,
103105
'-loglevel', 'warning', '-y')
104106
proc = await asyncio.subprocess.create_subprocess_exec('ffmpeg', *args, stdin=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,

0 commit comments

Comments
 (0)