Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. ;; -*- mode: emacs-lisp; coding: hebrew-iso-8bit-unix -*-
  2. ;; subtitles.el - work on .srt (subripper) subtitle files
  3. ;; Copyright (C) 2009 Ehud karni <ehud@...>
  4.  
  5. ;; This file is NOT part of GNU Emacs, distribution conditions below.
  6. ;;
  7. ;;              EHUD   KARNI            ינרק   דוהא
  8. ;;              Ben Gurion st'   14   ןוירוג ןב 'חר
  9. ;;              Kfar - Sava    44 257     אבס - רפכ
  10. ;;              ===================================
  11. ;;              ehud@...   972-9-7659599
  12. ;;              ===================================
  13.  
  14. ;;     RCS: $Id: subtitles.el,v 1.100 2009/05/16 14:10:45 ehud Exp $
  15.  
  16. ;;  $Log: subtitles.el,v $
  17. ;;  Revision 1.100  2009/05/16 14:10:45  ehud
  18. ;;  Initial RCS version
  19. ;;
  20.  
  21. ;; some functions to manipulate the times on an .srt (subripper) subtitle file
  22. ;;
  23. ;; An .srt file is composed of groups like that:
  24. ;;
  25. ;; line    content          * <-- column 1
  26. ;;   1   subtitle number    6
  27. ;;   2   subtitle times     00:01:34,920 --> 00:01:36,560
  28. ;;  3-+  subtitle value     ---any value in any language ---
  29. ;; last  separator          (empty)
  30. ;;
  31. ;; The user (interactive) functions are:
  32. ;;
  33. ;;   srt-renumber-subtitles - renumber all subtitles from 1 (no time change)
  34. ;;
  35. ;;   srt-offset-subtitles - change times by number of seconds (e.g. -2.74)
  36. ;;
  37. ;;   srt-mult-subtitles - change times linearly by multiplying (e.g. 1.04167)
  38. ;;         srt-23976-to-25-subtitles === (srt-mult-subtitles 25/23.976)
  39. ;;         srt-25-to-23976-subtitles === (srt-mult-subtitles 23.976/25)
  40. ;;
  41. ;;   srt-convert-sub-to-srt (fps) - convert a .sub file (microdvd) format to
  42. ;;                                  the .srt (subripper) format.
  43. ;;
  44. ;;  Ehud Karni 16/5/2009
  45.  
  46. ;;  This program is free software; you can redistribute it and/or modify
  47. ;;  it under the terms of the GNU General Public License as published by
  48. ;;  the Free Software Foundation; either version 2 of the License, or
  49. ;;  (at your option) any later version.
  50. ;;
  51. ;;  This program is distributed in the hope that it will be useful,
  52. ;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
  53. ;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  54. ;;  GNU General Public License for more details.
  55. ;;
  56. ;;  You should have received a copy of the GNU General Public License
  57. ;;  along with this program; if not, write to the Free Software
  58. ;;  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  59.  
  60.  
  61.  
  62. (defun srt-next-N-time ()
  63.   "Find the next srt subtitle number & times.
  64. returns a list with 3 elements : number, start-time (milliseconds), stop-time"
  65.        (let ((time-rgx "\\(0[0-9]:[0-5][0-9]:[0-5][0-9],[0-9][0-9][0-9]\\)")    ;; HH:mm:ss.nnn
  66.              N strt stop)
  67.            (and (re-search-forward (concat "^\\([0-9]+\\)\n"  time-rgx " --> " time-rgx "$")
  68.                                   nil t)               ;; search for next
  69.                (setq N (string-to-number (match-string 1))
  70.                      strt (srt-time-string-2-milli (match-string 2))
  71.                      stop (srt-time-string-2-milli (match-string 3)))
  72.                (list N strt stop))))
  73.  
  74.  
  75. (defun srt-time-string-2-milli (time)
  76.   "Convert srt TIME string (HH:MM:SS.mmm) to milliseconds"
  77.        (let ((HH (string-to-number (substring time 0 2)))
  78.              (MM (string-to-number (substring time 3 5)))
  79.              (SS (string-to-number (substring time 6 8)))
  80.              (ms (string-to-number (substring time 9 12))))
  81.            (+ (* (+ (* (+ (* HH 60) MM) 60) SS) 1000) ms)))
  82.  
  83.  
  84. (defun srt-time-milli-2-string (time)
  85.   "Convert srt TIME in milliseconds to string (HH:MM:SS.mmm)"
  86.        (let ((HH (/ time 3600000))
  87.              (MM (% (/ time 60000) 60))
  88.              (SS (% (/ time 1000) 60))
  89.              (ms (% time 1000)))
  90.            (format "%02d:%02d:%02d,%03d" HH MM SS ms)))
  91.  
  92.  
  93. (defun srt-time-string-replace (N strt stop)
  94.   "Replace last matched subtitle header by new values. 3 args:
  95. N - subtitle number, STRT - start time in milliseconds, STOP - stop time."
  96.        (replace-match (format "%d\n%s --> %s" N
  97.                               (srt-time-milli-2-string strt)
  98.                               (srt-time-milli-2-string stop)) t t))
  99.  
  100.  
  101. (defun srt-renumber-subtitles ()
  102.   "Renumber all subtitles starting with 1"
  103.   (interactive)
  104.        (let ((NEW 1)
  105.              (svd-pos (point))         ;; saved position
  106.              sub-va)                   ;; subtitle values
  107.            (goto-char (point-min))
  108.            (while (setq sub-va (srt-next-N-time))
  109.                (srt-time-string-replace NEW (nth 1 sub-va) (nth 2 sub-va))
  110.                (setq NEW (1+ NEW)))
  111.            (goto-char svd-pos)))
  112.  
  113.  
  114. (defun srt-offset-subtitles (seconds)
  115.   "Offset all subtitles by some SECONDS (float, e.g. -2.74)"
  116.   (interactive "NSeconds to offset (float e.g. -2.74)  ")
  117.        (let ((off (truncate (* 1000 seconds)))     ;; offset in milliseconds
  118.              (svd-pos (point))                     ;; saved position
  119.              sub-va)                               ;; subtitle values
  120.            (goto-char (point-min))
  121.            (while (setq sub-va (srt-next-N-time))
  122.                (srt-time-string-replace (car sub-va)
  123.                                         (+ (nth 1 sub-va) off)
  124.                                         (+ (nth 2 sub-va) off)))
  125.            (goto-char svd-pos)))
  126.  
  127.  
  128. (defun srt-mult-subtitles (rate)
  129.   "Multiply all subtitles time by this value (float, e.g. 1.042709, 0.959040)"
  130.   (interactive "NStrech time by (float e.g. 1.042709, 0.959040)  ")
  131.        (let ((svd-pos (point))                     ;; saved position
  132.              sub-va)                               ;; subtitle values
  133.            (goto-char (point-min))
  134.            (while (setq sub-va (srt-next-N-time))
  135.                (srt-time-string-replace (car sub-va)
  136.                                         (truncate (* (nth 1 sub-va) rate))
  137.                                         (truncate (* (nth 2 sub-va) rate))))
  138.            (goto-char svd-pos)))
  139.  
  140.  
  141.  
  142. (defun srt-25-to-23976-subtitles ()
  143.   "Convert all subtitles time from 25 fps to 23.976 fps"
  144.   (interactive)
  145.        (srt-mult-subtitles 0.95904))
  146.  
  147. (defun srt-23976-to-25-subtitles ()
  148.   "Convert all subtitles time from 23.976 fps to 25 fps"
  149.   (interactive)
  150.        (srt-mult-subtitles 1.042709376))
  151.  
  152.  
  153. (defun srt-convert-sub-to-srt (fps)
  154.   "Convert a .sub file (microdvd) to an .srt format.
  155. 1 arg: FPS - frames per second."
  156. ;; .sub (microdvd) format is:
  157. ;; {start-frame}{stop-frame}line1_text|line2_text
  158.   (interactive "NFrames per second (float e.g. 23.976, 25)  ")
  159.        (let ((svd-pos (point-marker))              ;; saved position
  160.              (NEW 1)                               ;; subtitle number
  161.              strt stop text)
  162.            (setq fps (/ 1000.0 fps))               ;; frame time in ms (float)
  163.            (goto-char (point-min))
  164.            (while (re-search-forward "^{\\([0-9]+\\)}{\\([0-9]+\\)}\\(.*\\)$" nil t)   ;; search for next
  165.                (setq strt (truncate (* fps (string-to-number (match-string 1)))))
  166.                (setq stop (truncate (* fps (string-to-number (match-string 2)))))
  167.                (setq text (match-string 3))
  168.                (srt-time-string-replace NEW strt stop)
  169.                (insert "\n" text "\n")
  170.                (setq NEW (1+ NEW)))
  171.            (goto-char (point-min))
  172.            (while (search-forward "|" nil t)
  173.                (replace-match "\n"))
  174.            (goto-char svd-pos)))
  175.  
  176. ;;=========================== end of subtitles.el ======================