From b41440330b8503f9f7d3efef27539351373e72a8 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 7 Jan 2015 21:15:02 -0500 Subject: [PATCH] First commit. --- .gitignore | 8 +++ Makefile.am | 1 + README.md | 44 +++++++++++++ configure.ac | 12 ++++ srt2vtt | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 238 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100644 README.md create mode 100644 configure.ac create mode 100755 srt2vtt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc022ad --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/Makefile.in +/Makefile +/aclocal.m4 +/autom4te.cache/ +/build-aux/ +/config.log +/config.status +/configure diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..014d4e9 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +bin_SCRIPTS = srt2vtt diff --git a/README.md b/README.md new file mode 100644 index 0000000..dc71bbf --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +srt2vtt +======= + +Convert SRT formatted subtitles to WebVTT format for use with the +HTML5 `` tag. + +Usage +----- + +``` +$ srt2vtt --help +Usage: srt2vtt [OPTIONS] +Convert SubRip formatted subtitles to WebVTT format. + + -h, --help display this help and exit + -v, --version display version and exit + -i, --input=FILE-NAME read input from FILE-NAME + -o, --output=FILE-NAME write output to FILE-NAME +``` + +If `--input` or `--output` is ommitted, read from stdin or stdout, +respectively. + +Installation +------------ + +``` +autoreconf -vif +./configure +make install +``` + +Alternatively, just copy `srt2vtt` yourself to wherever you would like +it. Or, call it from your own git checkout. + +Requirements +------------ + +* GNU Guile >= 2.0.5 + +License +------- + +GNU GPLv3+ diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..20d3e3b --- /dev/null +++ b/configure.ac @@ -0,0 +1,12 @@ +dnl -*- Autoconf -*- + +AC_INIT(srt2vtt, 0.1) +AC_CONFIG_AUX_DIR([build-aux]) +AM_INIT_AUTOMAKE([foreign]) +AM_SILENT_RULES([yes]) + +AC_CONFIG_FILES([Makefile]) + +GUILE_PROGS([2.0.5]) + +AC_OUTPUT diff --git a/srt2vtt b/srt2vtt new file mode 100755 index 0000000..34ba105 --- /dev/null +++ b/srt2vtt @@ -0,0 +1,173 @@ +#!/usr/bin/guile --no-auto-compile +-*- scheme -*- +!# + +;;; srt2vtt --- SRT to WebVTT converter +;;; Copyright © 2015 David Thompson +;;; +;;; srt2vtt is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; srt2vtt is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Haunt. If not, see . + +;;; Commentary: +;; +;; Convert SRT formatted subtitles to WebVTT format. +;; +;;; Code: + +(use-modules (ice-9 format) + (ice-9 match) + (ice-9 rdelim) + (ice-9 regex) + (srfi srfi-1) + (srfi srfi-9) + (srfi srfi-11) + (srfi srfi-26) + (srfi srfi-37)) + +(define-record-type + (make-subtitle id start end text) + subtitle? + (id subtitle-id) + (start subtitle-start) + (end subtitle-end) + (text subtitle-text)) + +(define parse-time + (let ((regexp (make-regexp "([0-9]+):([0-9]+):([0-9]+),([0-9]+)"))) + (lambda (s) + (let ((match (regexp-exec regexp s))) + (map (cut match:substring match <>) '(1 2 3 4)))))) + +(define parse-time-span + (let ((regexp (make-regexp "([0-9:,]+) --> ([0-9:,]+)"))) + (lambda (s) + (let ((match (regexp-exec regexp s))) + (values (parse-time (match:substring match 1)) + (parse-time (match:substring match 2))))))) + +(define (read-sub-rip port) + (let-values (((id) (string->number (read-line port))) + ((start end) (parse-time-span (read-line port))) + ((lines) (let loop ((lines '())) + (let ((line (read-line port))) + (if (string-null? line) + lines + (loop (cons line lines))))))) + (make-subtitle id start end lines))) + +(define (read-sub-rips port) + (reverse + (let loop ((subs '())) + (if (eof-object? (peek-char port)) + subs + (loop (cons (read-sub-rip port) subs)))))) + +(define (write-time time port) + (match time + ((h m s ms) + (format port "~a:~a:~a.~a" h m s ms)))) + +(define (write-web-vtt subtitle port) + (match subtitle + (($ id start end text) + (format port "~a~%" id) + (write-time start port) + (display " --> " port) + (write-time end port) + (newline port) + (format port "~a~%" (string-join text "\n")) + (newline port)))) + +(define (write-web-vtts subtitles port) + (display "WEBVTT\n" port) + (for-each (cut write-web-vtt <> port) subtitles)) + +(define (convert input-port output-port) + (write-web-vtts (read-sub-rips input-port) output-port)) + +(define (show-help-and-exit) + (format #t "Usage: srt2vtt [OPTIONS] +Convert SubRip formatted subtitles to WebVTT format.~%") + (display " + -h, --help display this help and exit") + (display " + -v, --version display version and exit") + (display " + -i, --input=FILE-NAME read input from FILE-NAME") + (display " + -o, --output=FILE-NAME write output to FILE-NAME") + (newline) + (exit 0)) + +(define (show-version-and-exit) + (format #t "srt2vtt 0.1~%") + (exit 0)) + +(define (show-usage-and-exit) + (format #t "Try `srt2vtt --help' for more information.~%") + (exit 1)) + +(define (show-wrong-args-and-exit) + (format #t "Invalid arguments~%") + (show-usage-and-exit)) + +(define %default-args + `((input . ,(current-input-port)) + (output . ,(current-output-port)))) + +(define %options + (list (option '(#\h "help") #f #f + (lambda (opt name arg args) + (show-help-and-exit))) + (option '(#\v "version") #f #f + (lambda (opt name arg args) + (show-version-and-exit))) + (option '(#\i "input") #t #f + (lambda (opt name arg args) + (alist-cons 'input arg args))) + (option '(#\o "output") #t #f + (lambda (opt name arg args) + (alist-cons 'output arg args))))) + +(define (make-call-with-port-or-file file-proc) + (lambda (port-or-file proc) + (if (port? port-or-file) + (proc port-or-file) + (file-proc port-or-file proc)))) + +(define call-with-port-or-input-file + (make-call-with-port-or-file call-with-input-file)) + +(define call-with-port-or-output-file + (make-call-with-port-or-file call-with-output-file)) + +(define (parse-opts args) + (args-fold args + %options + (lambda (opt name arg args) + (error "Unrecognized option '~a'" name)) + (lambda (arg args) + (error "Extraneous argument '~a'" arg)) + %default-args)) + +(define (main args) + (let ((opts (parse-opts args))) + (call-with-port-or-input-file (assoc-ref opts 'input) + (lambda (input-port) + (call-with-port-or-output-file (assoc-ref opts 'output) + (lambda (output-port) + (convert input-port output-port))))))) + +(match (command-line) + ((arg0 args ...) + (main args))) -- 2.31.1