Compare commits
1 Commits
v0.14.0
...
m/mkv-subt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6656b75c1b |
@@ -28,6 +28,7 @@
|
||||
"languagedetect": "^1.1.1",
|
||||
"location-history": "^1.0.0",
|
||||
"material-ui": "^0.15.4",
|
||||
"matroska-subtitles": "^2.0.0",
|
||||
"musicmetadata": "^2.0.2",
|
||||
"network-address": "^1.1.0",
|
||||
"parse-torrent": "^5.7.3",
|
||||
|
||||
@@ -2,8 +2,10 @@ const electron = require('electron')
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const parallel = require('run-parallel')
|
||||
const zeroFill = require('zero-fill')
|
||||
|
||||
const remote = electron.remote
|
||||
const ipcRenderer = electron.ipcRenderer
|
||||
|
||||
const {dispatch} = require('../lib/dispatcher')
|
||||
|
||||
@@ -74,6 +76,7 @@ module.exports = class SubtitlesController {
|
||||
torrentSummary.progress.files.forEach((fp, ix) => {
|
||||
if (fp.numPieces !== fp.numPiecesPresent) return // ignore incomplete files
|
||||
var file = torrentSummary.files[ix]
|
||||
if (this.state.playing.fileIndex === ix) return this.checkForEmbeddedMKVSubtitles(file)
|
||||
if (!this.isSubtitle(file.name)) return
|
||||
var filePath = path.join(torrentSummary.path, file.path)
|
||||
this.addSubtitles([filePath], false)
|
||||
@@ -85,12 +88,31 @@ module.exports = class SubtitlesController {
|
||||
var ext = path.extname(name).toLowerCase()
|
||||
return ext === '.srt' || ext === '.vtt'
|
||||
}
|
||||
|
||||
checkForEmbeddedMKVSubtitles (file) {
|
||||
var playing = this.state.playing
|
||||
// var playingFile = this.state.getPlayingFileSummary()
|
||||
// var playingPath = path.join(torrentSummary.path, playingFile.path)
|
||||
|
||||
if (path.extname(file.name).toLowerCase() === '.mkv') {
|
||||
ipcRenderer.send('wt-get-mkv-subtitles', playing.infoHash, playing.fileIndex)
|
||||
|
||||
ipcRenderer.once('wt-mkv-subtitles', function (e, tracks) {
|
||||
tracks.forEach(function (trackEntry) {
|
||||
var track = loadEmbeddedSubtitle(trackEntry)
|
||||
console.log('loaded emb subs', track)
|
||||
playing.subtitles.tracks.push(track)
|
||||
})
|
||||
|
||||
if (tracks.length > 0) relabelSubtitles(playing.subtitles)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadSubtitle (file, cb) {
|
||||
// Lazy load to keep startup fast
|
||||
var concat = require('simple-concat')
|
||||
var LanguageDetect = require('languagedetect')
|
||||
var srtToVtt = require('srt-to-vtt')
|
||||
|
||||
// Read the .SRT or .VTT file, parse it, add subtitle track
|
||||
@@ -101,11 +123,7 @@ function loadSubtitle (file, cb) {
|
||||
concat(vttStream, function (err, buf) {
|
||||
if (err) return dispatch('error', 'Can\'t parse subtitles file.')
|
||||
|
||||
// Detect what language the subtitles are in
|
||||
var vttContents = buf.toString().replace(/(.*-->.*)/g, '')
|
||||
var langDetected = (new LanguageDetect()).detect(vttContents, 2)
|
||||
langDetected = langDetected.length ? langDetected[0][0] : 'subtitle'
|
||||
langDetected = langDetected.slice(0, 1).toUpperCase() + langDetected.slice(1)
|
||||
var langDetected = detectVTTLanguage(buf)
|
||||
|
||||
var track = {
|
||||
buffer: 'data:text/vtt;base64,' + buf.toString('base64'),
|
||||
@@ -137,3 +155,49 @@ function relabelSubtitles (subtitles) {
|
||||
track.label = counts[lang] > 1 ? (lang + ' ' + counts[lang]) : lang
|
||||
})
|
||||
}
|
||||
|
||||
function detectVTTLanguage (buffer) {
|
||||
var LanguageDetect = require('languagedetect')
|
||||
|
||||
// Detect what language the subtitles are in
|
||||
var vttContents = buffer.toString().replace(/(.*-->.*)/g, '') // remove numbers?
|
||||
var langDetected = (new LanguageDetect()).detect(vttContents, 2)
|
||||
langDetected = langDetected.length ? langDetected[0][0] : 'subtitle'
|
||||
langDetected = langDetected.slice(0, 1).toUpperCase() + langDetected.slice(1)
|
||||
|
||||
return langDetected
|
||||
}
|
||||
|
||||
function loadEmbeddedSubtitle (trackEntry) {
|
||||
// convert to .vtt format
|
||||
var vtt = 'WEBVTT FILE\r\n\r\n'
|
||||
trackEntry.subtitles.forEach(function (sub, i) {
|
||||
vtt += `${i + 1}\r\n`
|
||||
vtt += `${msToTime(sub.time)} --> ${msToTime(sub.time + sub.duration)}\r\n`
|
||||
vtt += `${sub.text}\r\n\r\n`
|
||||
})
|
||||
|
||||
function msToTime (s) {
|
||||
var ms = s % 1000
|
||||
s = (s - ms) / 1000
|
||||
var secs = s % 60
|
||||
s = (s - secs) / 60
|
||||
var mins = s % 60
|
||||
var hrs = (s - mins) / 60
|
||||
|
||||
var z = zeroFill
|
||||
return z(2, hrs) + ':' + z(2, mins) + ':' + z(2, secs) + '.' + z(3, ms)
|
||||
}
|
||||
|
||||
var buf = new Buffer(vtt)
|
||||
var langDetected = detectVTTLanguage(buf)
|
||||
|
||||
var track = {
|
||||
buffer: 'data:text/vtt;base64,' + buf.toString('base64'),
|
||||
language: langDetected,
|
||||
label: langDetected,
|
||||
filePath: null
|
||||
}
|
||||
|
||||
return track
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ function init () {
|
||||
generateTorrentPoster(torrentKey))
|
||||
ipc.on('wt-get-audio-metadata', (e, infoHash, index) =>
|
||||
getAudioMetadata(infoHash, index))
|
||||
ipc.on('wt-get-mkv-subtitles', (e, infoHash, index) =>
|
||||
getMKVSubtitles(infoHash, index))
|
||||
ipc.on('wt-start-server', (e, infoHash, index) =>
|
||||
startServer(infoHash, index))
|
||||
ipc.on('wt-stop-server', (e) =>
|
||||
@@ -342,6 +344,32 @@ function getAudioMetadata (infoHash, index) {
|
||||
})
|
||||
}
|
||||
|
||||
function getMKVSubtitles (infoHash, index) {
|
||||
var torrent = client.get(infoHash)
|
||||
var file = torrent.files[index]
|
||||
|
||||
var MatroskaSubtitles = require('matroska-subtitles')
|
||||
var subtitleParser = new MatroskaSubtitles()
|
||||
|
||||
var textTracks = new Map()
|
||||
|
||||
subtitleParser.once('tracks', function (tracks) {
|
||||
tracks.forEach(function (track) {
|
||||
textTracks.set(track.number, { track: track, subtitles: [] })
|
||||
})
|
||||
})
|
||||
|
||||
subtitleParser.on('subtitle', function (subtitle, trackNumber) {
|
||||
textTracks.get(trackNumber).subtitles.push(subtitle)
|
||||
})
|
||||
|
||||
subtitleParser.on('finish', function () {
|
||||
ipc.send('wt-mkv-subtitles', Array.from(textTracks.values()))
|
||||
})
|
||||
|
||||
file.createReadStream().pipe(subtitleParser)
|
||||
}
|
||||
|
||||
function selectFiles (torrentOrInfoHash, selections) {
|
||||
// Get the torrent object
|
||||
var torrent
|
||||
|
||||
Reference in New Issue
Block a user