Skip to content

Commit

Permalink
Merge pull request #36 from hockyy/feature/34
Browse files Browse the repository at this point in the history
[#34] Add support to watch youtube video in Miteiru
  • Loading branch information
hockyy authored Jul 25, 2023
2 parents 392657b + 2d91547 commit 2c46b9c
Show file tree
Hide file tree
Showing 11 changed files with 641 additions and 114 deletions.
9 changes: 9 additions & 0 deletions copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const fs = require('fs-extra');
const path = require('path');

const sourceDir = path.join(__dirname, 'renderer', 'public');
const destDir = path.join(__dirname, 'app');

fs.copy(sourceDir, destDir)
.then(() => console.log('Files copied successfully!'))
.catch(err => console.error(err));
15 changes: 13 additions & 2 deletions main/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import fs from "fs";
import path from "path";
import {getTokenizer} from "kuromojin";
import {getSubtitles} from "./helpers/getSubtitles";


const isProd: boolean = process.env.NODE_ENV === 'production';
Expand Down Expand Up @@ -118,6 +119,16 @@ if (isProd) {
ipcMain.handle('tags', (event) => {
return JMDict.tags;
})
ipcMain.handle('getYoutubeSubtitle', async (event, videoID, lang) => {
// Fetching Subtitles
try {
return await getSubtitles({videoID, lang})
} catch (error) {
console.error('Error fetching subtitles:', error);
return []
}

})
ipcMain.handle('pickDirectory', async (event) => {
return await dialog.showOpenDialog({
properties:
Expand Down Expand Up @@ -160,7 +171,7 @@ if (isProd) {
if (filePath && !canceled) {
fs.writeFile(filePath, saveData, (err) => {
if (err) throw err;
console.log('The file has been saved!');
console.info('The file has been saved!');
});
}

Expand Down Expand Up @@ -271,7 +282,7 @@ if (isProd) {
getTokenizer({dicPath: path.join(__dirname, 'dict/')}).then(loadedTokenizer => {
tokenizer = loadedTokenizer;
}).catch(e => {
console.log(e)
console.error(e)
})
ipcMain.handle('tokenizeUsingKuromoji', async (event, sentence) => {
return tokenizer.tokenizeForSentence(sentence);
Expand Down
70 changes: 70 additions & 0 deletions main/helpers/getSubtitles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* @flow */

import axios from 'axios';
import {find} from 'lodash';
import {decode} from 'html-entities';

function stripTags(input, allowedTags = [], replacement = '') {
// Create a string of allowed tags, joined by '|'
let tags = allowedTags.join('|');

// Create a new RegExp object
let regex = new RegExp(`<(?!\/?(${tags})[^>]*)\/?.*?>`, 'g');

// Replace disallowed tags with replacement string
return input.replace(regex, replacement);
}

export async function getSubtitles({videoID, lang = 'ja'}) {
const {data} = await axios.get(
`https://youtube.com/watch?v=${videoID}`
);

// * ensure we have access to captions data
if (!data.includes('captionTracks'))
throw new Error(`Could not find captions for video: ${videoID}`);

const regex = /({"captionTracks":.*isTranslatable":(true|false)}])/;
const [match] = regex.exec(data);
const {captionTracks} = JSON.parse(`${match}}`);

const subtitle =
find(captionTracks, {
vssId: `.${lang}`,
}) ||
find(captionTracks, {
vssId: `a.${lang}`,
}) ||
find(captionTracks, ({vssId}) => vssId && vssId.match(`.${lang}`));

// * ensure we have found the correct subtitle lang
if (!subtitle || (subtitle && !subtitle.baseUrl))
throw new Error(`Could not find ${lang} captions for ${videoID}`);

const {data: transcript} = await axios.get(subtitle.baseUrl);
return transcript
.replace('<?xml version="1.0" encoding="utf-8" ?><transcript>', '')
.replace('</transcript>', '')
.split('</text>')
.filter(line => line && line.trim())
.map(line => {
const startRegex = /start="([\d.]+)"/;
const durRegex = /dur="([\d.]+)"/;

const [, start] = startRegex.exec(line);
const [, dur] = durRegex.exec(line);

const htmlText = line
.replace(/<text.+>/, '')
.replace(/&amp;/gi, '&')
.replace(/<\/?[^>]+(>|$)/g, '');
const decodedText = decode(htmlText);
const text = stripTags(decodedText);

return {
start,
dur,
text,
};
});
}
Loading

0 comments on commit 2c46b9c

Please sign in to comment.