Simple extensible ASS subtitle editor for Linux
- Python - extend it however you want with ease
- Video preview
- Audio preview (spectrogram)
- Audio and video are synced at all times
- Spectrogram range selection for eases timing
- Spectrogram shows where subs start and end
- Slow playback support
- I can sub an entire episode without ever having to touch the mouse
- Mouse users are not excluded and can click their way to all the commands
- Robust plugin API (everything GUI is capable of can be done through the API)
- Simple architecture (Commands ↔ API ↔ GUI)
- Separate control for persistent inline comments (useful for translating)
- Newlines support in the editor
- Seeking is aligned to video frames
- Style editor with realistic preview (taken from video source)
- No bloat
Planned features
- Documentation
- Hotkeys
- Built-in commands
- Configuration files
- The API
- Meta data editor
Screenshot:
- Install system dependencies
- Clone the repository:
git clone https://github.com/rr-/bubblesub
- Enter its directory:
cd bubblesub
- Install
bubblesub
:pip install --user .
~/.config/bubblesub/scripts
: contains user plugins~/.config/bubblesub/
: contains user configuration in JSON (subject to change, please back it up between upgrades)~/.cache/bubblesub/
: used to cache time codes and such
import io
import asyncio
import speech_recognition as sr
from bubblesub.api.cmd import PluginCommand
LANGUAGE = 'ja'
async def _work(api, logger, line):
logger.info('line #{} - analyzing'.format(line.number))
recognizer = sr.Recognizer()
try:
def recognize():
with io.BytesIO() as handle:
api.audio.save_wav(handle, line.start, line.end)
handle.seek(0, io.SEEK_SET)
with sr.AudioFile(handle) as source:
audio = recognizer.record(source)
return recognizer.recognize_google(audio, language=LANGUAGE)
# don't clog the UI thread
note = await asyncio.get_event_loop().run_in_executor(None, recognize)
except sr.UnknownValueError:
logger.warn('line #{}: not recognized'.format(line.number))
except sr.RequestError as ex:
logger.error('line #{}: error ({})'.format(line.number, ex))
else:
logger.info('line #{}: OK'.format(line.number))
if line.note:
line.note = line.note + r'\N' + note
else:
line.note = note
class SpeechRecognitionCommand(PluginCommand):
name = 'grid/speech-recognition'
menu_name = 'Speech recognition'
def enabled(self):
return self.api.subs.has_selection and self.api.audio.has_audio_source
async def run(self):
for line in self.api.subs.selected_lines:
await _work(self.api, self, line)
-
Why not aegisub?
As of August 2017:
- It's dead
- Forum is down for two months
- Bug tracker is down for much longer
- Pull requests are ignored
- It has numerous unfixed bugs
- It often crashes
- Recent menu wasn't working for at least 2 years
- Karaoke joining never worked to begin with
- Its API is very limited and I can't write the plugins I need
- Its code is complicated making it hard to add features to
- It's dead
-
Windows builds?
This is a hobby project and wrestling with Windows to have it compile a single C dependency library isn't my idea of a well-spent afternoon. It should be possible with MSYS2.
-
I want to report a bug.
Please use GitHub issues.
-
I want a feature.
Chances are I'm too busy to work on features I don't personally need, so pull requests are strongly encouraged.