From e7e97a7f6012abef3d9f491efde0f6ab0d5d4f99 Mon Sep 17 00:00:00 2001 From: Azeufack Noupeu Willy Date: Thu, 13 Nov 2025 13:07:18 +0100 Subject: [PATCH 01/37] feat(S2-02b): Implement AssemblyAI external transcription with speaker diarization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add assembly.ts module for REST API transcription via AssemblyAI - Implement 5-step pipeline: upload → create job → poll status → download → save - Enable speaker_labels for diarization (Speaker A, B, C...) - Add millisecond-precision timestamps for each utterance - Store JSON transcripts in storage/transcripts/{session_id}.json - Add axios, dotenv dependencies - Add transcribeLatest.ts helper for quick testing User Story: S2-02b - Externe Transkription per REST API --- package-lock.json | 44 +++ package.json | 8 + .../modules/transcription/assembly.test.js | 14 + services/modules/transcription/assembly.ts | 133 ++++++++ .../modules/transcription/package-lock.json | 319 ++++++++++++++++++ services/modules/transcription/package.json | 9 + services/pipeline/jobs/transcribeLatest.ts | 52 +++ 7 files changed, 579 insertions(+) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 services/modules/transcription/assembly.test.js create mode 100644 services/modules/transcription/assembly.ts create mode 100644 services/modules/transcription/package-lock.json create mode 100644 services/modules/transcription/package.json create mode 100644 services/pipeline/jobs/transcribeLatest.ts diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4b57d9f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,44 @@ +{ + "name": "video2document", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "dotenv": "^17.2.3" + }, + "devDependencies": { + "@types/node": "^24.10.0" + } + }, + "node_modules/@types/node": { + "version": "24.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", + "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..48d43a3 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "dotenv": "^17.2.3" + }, + "devDependencies": { + "@types/node": "^24.10.0" + } +} diff --git a/services/modules/transcription/assembly.test.js b/services/modules/transcription/assembly.test.js new file mode 100644 index 0000000..66ce753 --- /dev/null +++ b/services/modules/transcription/assembly.test.js @@ -0,0 +1,14 @@ +import 'dotenv/config'; +import assemblyModule from './assembly.ts'; + +// Test: URL passed as argument OR local file ./storage/audio/test.wav +const audioPath = process.argv[2] || './storage/audio/test.wav'; + +assemblyModule.run(audioPath) + .then(result => { + console.log('✅ Success!'); + console.log('Transcript ID:', result.id); + }) + .catch(error => { + console.error('❌ Error:', error?.message || error); + }); diff --git a/services/modules/transcription/assembly.ts b/services/modules/transcription/assembly.ts new file mode 100644 index 0000000..46fe236 --- /dev/null +++ b/services/modules/transcription/assembly.ts @@ -0,0 +1,133 @@ +import 'dotenv/config'; +import axios from 'axios'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const API_KEY = process.env.ASSEMBLYAI_API_KEY; +const BASE_URL = 'https://api.assemblyai.com/v2'; + +/** + * Uploads audio file to AssemblyAI + */ +async function uploadAudio(audioPath: string): Promise { + const audioData = fs.readFileSync(audioPath); + + const response = await axios.post<{ upload_url: string }>(`${BASE_URL}/upload`, audioData, { + headers: { + 'authorization': API_KEY, + 'content-type': 'application/octet-stream' + } + }); + + return response.data.upload_url; +} + +/** + * Extract a session id (basename without extension) from a local path or a URL + */ +function getSessionId(inputPath: string): string { + try { + const parsed = new URL(inputPath); + const base = path.basename(parsed.pathname); + return base.replace(/\.[^.]+$/, ''); + } catch (err) { + // not a URL, treat as local path + return path.basename(inputPath, path.extname(inputPath)); + } +} + +/** + * Creates transcription job with speaker diarization + */ +async function createTranscript(audioUrl: string): Promise { + const response = await axios.post<{ id: string }>(`${BASE_URL}/transcript`, { + audio_url: audioUrl, + speaker_labels: true, + language_detection: true + }, { + headers: { + 'authorization': API_KEY, + 'content-type': 'application/json' + } + }); + + return response.data.id; +} + +/** + * Polls transcript status until completed + */ +async function pollTranscript(transcriptId: string): Promise { + while (true) { + const response = await axios.get(`${BASE_URL}/transcript/${transcriptId}`, { + headers: { 'authorization': API_KEY } + }); + + const status = response.data.status; + + if (status === 'completed') { + return response.data; + } else if (status === 'error') { + throw new Error(`Transcription failed: ${response.data.error}`); + } + + // Wait 3 seconds before next poll + await new Promise(resolve => setTimeout(resolve, 3000)); + } +} + +/** + * Saves transcript to storage + */ +function saveTranscript(transcript: any, sessionId: string): void { + const outputDir = path.join(__dirname, '..', '..', '..', 'storage', 'transcripts'); + + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + const outputPath = path.join(outputDir, `${sessionId}.json`); + fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2)); + + console.log(`✅ Transcript saved: ${outputPath}`); +} + +export default { + name: "assembly", + type: "transcription", + displayname: "AssemblyAI", + run: async (audioPath: string) => { + try { + // Determine if audioPath is an external URL or a local file + let audioUrl: string; + if (/^https?:\/\//i.test(audioPath)) { + console.log('🔗 Using external audio URL...'); + audioUrl = audioPath; + } else { + console.log('🔄 Uploading local audio...'); + if (!fs.existsSync(audioPath)) { + throw new Error(`Audio file not found: ${audioPath}`); + } + audioUrl = await uploadAudio(audioPath); + } + + console.log('🔄 Creating transcript job...'); + const transcriptId = await createTranscript(audioUrl); + + console.log('⏳ Waiting for transcription...'); + const transcript = await pollTranscript(transcriptId); + + const sessionId = getSessionId(audioPath); + saveTranscript(transcript, sessionId); + + return transcript; + } catch (error: any) { + console.error('❌ Transcription error:', error.message); + throw error; + } + } +}; \ No newline at end of file diff --git a/services/modules/transcription/package-lock.json b/services/modules/transcription/package-lock.json new file mode 100644 index 0000000..58c2913 --- /dev/null +++ b/services/modules/transcription/package-lock.json @@ -0,0 +1,319 @@ +{ + "name": "transcription", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "axios": "^1.13.2" + }, + "devDependencies": { + "@types/axios": "^0.9.36", + "@types/node": "^24.10.0" + } + }, + "node_modules/@types/axios": { + "version": "0.9.36", + "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.9.36.tgz", + "integrity": "sha512-NLOpedx9o+rxo/X5ChbdiX6mS1atE4WHmEEIcR9NLenRVa5HoVjAvjafwU3FPTqnZEstpoqCaW7fagqSoTDNeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", + "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/services/modules/transcription/package.json b/services/modules/transcription/package.json new file mode 100644 index 0000000..6d24fe5 --- /dev/null +++ b/services/modules/transcription/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "axios": "^1.13.2" + }, + "devDependencies": { + "@types/axios": "^0.9.36", + "@types/node": "^24.10.0" + } +} diff --git a/services/pipeline/jobs/transcribeLatest.ts b/services/pipeline/jobs/transcribeLatest.ts new file mode 100644 index 0000000..fc75ad5 --- /dev/null +++ b/services/pipeline/jobs/transcribeLatest.ts @@ -0,0 +1,52 @@ +// services/pipeline/jobs/transcribeLatest.ts +import path from 'path'; +import fs from 'fs'; +import assembly from '../../modules/transcription/assembly'; + +/** + * Finds the most recently modified .wav file in storage/audio/ + */ +function getLatestWav(): string { + const audioDir = path.join(process.cwd(), 'storage', 'audio'); + const files = fs.readdirSync(audioDir).filter(f => f.toLowerCase().endsWith('.wav')); + if (files.length === 0) throw new Error('⚠️ No .wav file found in storage/audio'); + + const newest = files + .map(f => ({ f, t: fs.statSync(path.join(audioDir, f)).mtimeMs })) + .sort((a, b) => b.t - a.t)[0].f; + + return path.join(audioDir, newest); +} + +/** + * Full transcription pipeline according to the defined workflow: + * 1. Audio Upload → AssemblyAI + * 2. Job Creation (transcript_id) + * 3. Polling Status (queued → processing → completed) + * 4. Download Transcript JSON + * 5. Storage: /transcripts/{session_id}.json + */ +async function main() { + const audioPath = getLatestWav(); + + console.log('1️⃣ Audio Upload → AssemblyAI'); + console.log(' Source:', audioPath); + + console.log('2️⃣ Job Creation (transcript_id)'); + console.log('3️⃣ Polling Status (queued → processing → completed)'); + console.log('4️⃣ Download Transcript JSON'); + console.log('5️⃣ Storage: /transcripts/{session_id}.json'); + + // Execute the transcription process via the AssemblyAI module + const result = await assembly.run(audioPath); + + console.log('✅ Transcription completed successfully'); + console.log('🆔 Transcript ID:', result.id); + console.log('📁 Transcript file saved under: storage/transcripts/'); +} + +// Entry point +main().catch((err) => { + console.error('❌ Transcription pipeline failed:', err.message || err); + process.exit(1); +}); From 9254ddc57f019b37202e04abae7ebf60bfd6bbb9 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Thu, 13 Nov 2025 17:34:22 +0100 Subject: [PATCH 02/37] Changed the Folder Structure for better maintainability --- .../modules/transcription/{ => remote/assembly_AI}/assembly.js | 0 .../transcription/{ => remote/assembly_AI}/assembly.test.js | 0 .../modules/transcription/{ => remote/assembly_AI}/assembly.ts | 0 .../modules/transcription/{ => remote/assembly_AI}/example.js | 0 .../transcription/{ => remote/assembly_AI}/package-lock.json | 0 .../modules/transcription/{ => remote/assembly_AI}/package.json | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename services/modules/transcription/{ => remote/assembly_AI}/assembly.js (100%) rename services/modules/transcription/{ => remote/assembly_AI}/assembly.test.js (100%) rename services/modules/transcription/{ => remote/assembly_AI}/assembly.ts (100%) rename services/modules/transcription/{ => remote/assembly_AI}/example.js (100%) rename services/modules/transcription/{ => remote/assembly_AI}/package-lock.json (100%) rename services/modules/transcription/{ => remote/assembly_AI}/package.json (100%) diff --git a/services/modules/transcription/assembly.js b/services/modules/transcription/remote/assembly_AI/assembly.js similarity index 100% rename from services/modules/transcription/assembly.js rename to services/modules/transcription/remote/assembly_AI/assembly.js diff --git a/services/modules/transcription/assembly.test.js b/services/modules/transcription/remote/assembly_AI/assembly.test.js similarity index 100% rename from services/modules/transcription/assembly.test.js rename to services/modules/transcription/remote/assembly_AI/assembly.test.js diff --git a/services/modules/transcription/assembly.ts b/services/modules/transcription/remote/assembly_AI/assembly.ts similarity index 100% rename from services/modules/transcription/assembly.ts rename to services/modules/transcription/remote/assembly_AI/assembly.ts diff --git a/services/modules/transcription/example.js b/services/modules/transcription/remote/assembly_AI/example.js similarity index 100% rename from services/modules/transcription/example.js rename to services/modules/transcription/remote/assembly_AI/example.js diff --git a/services/modules/transcription/package-lock.json b/services/modules/transcription/remote/assembly_AI/package-lock.json similarity index 100% rename from services/modules/transcription/package-lock.json rename to services/modules/transcription/remote/assembly_AI/package-lock.json diff --git a/services/modules/transcription/package.json b/services/modules/transcription/remote/assembly_AI/package.json similarity index 100% rename from services/modules/transcription/package.json rename to services/modules/transcription/remote/assembly_AI/package.json From 79e0c487558bd2084e523212dc4a7728dc526aaa Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Thu, 13 Nov 2025 17:35:40 +0100 Subject: [PATCH 03/37] Reduced Number of test paths to avoid redundancy --- {tests => test}/integration/.gitkeep | 0 {tests => test}/unit/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {tests => test}/integration/.gitkeep (100%) rename {tests => test}/unit/.gitkeep (100%) diff --git a/tests/integration/.gitkeep b/test/integration/.gitkeep similarity index 100% rename from tests/integration/.gitkeep rename to test/integration/.gitkeep diff --git a/tests/unit/.gitkeep b/test/unit/.gitkeep similarity index 100% rename from tests/unit/.gitkeep rename to test/unit/.gitkeep From d9eacafc3acc82bc40c24389e52520a0482d7641 Mon Sep 17 00:00:00 2001 From: Emily Date: Fri, 14 Nov 2025 14:28:11 +0100 Subject: [PATCH 04/37] fixed the program by moving the example module back to where the program can ACTUALLY load it --- .../{transcription/remote/assembly_AI => utility}/example.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename services/modules/{transcription/remote/assembly_AI => utility}/example.js (100%) diff --git a/services/modules/transcription/remote/assembly_AI/example.js b/services/modules/utility/example.js similarity index 100% rename from services/modules/transcription/remote/assembly_AI/example.js rename to services/modules/utility/example.js From 6083773f8888ba1689eedc41ce9bb7513041a491 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Sat, 15 Nov 2025 14:45:13 +0100 Subject: [PATCH 05/37] New Folder structure --- package-lock.json | 22 ++ package.json | 2 + scripts/.gitkeep | 0 scripts/commands.txt | 5 - scripts/extract.ts | 23 -- scripts/transcribe.ts | 18 - .../whisperLocal.ts | 3 +- .../assembly.js | 0 .../assembly.ts | 0 .../modules/transcription/local/whisper.cpp | 1 - .../remote/assembly_AI/package-lock.json | 319 ------------------ .../remote/assembly_AI/package.json | 9 - .../integration}/assembly.test.js | 2 +- 13 files changed, 26 insertions(+), 378 deletions(-) create mode 100644 scripts/.gitkeep delete mode 100644 scripts/commands.txt delete mode 100644 scripts/extract.ts delete mode 100644 scripts/transcribe.ts rename services/modules/{transcription/local => transcription-local}/whisperLocal.ts (90%) rename services/modules/{transcription/remote/assembly_AI => transcription-remote}/assembly.js (100%) rename services/modules/{transcription/remote/assembly_AI => transcription-remote}/assembly.ts (100%) delete mode 160000 services/modules/transcription/local/whisper.cpp delete mode 100644 services/modules/transcription/remote/assembly_AI/package-lock.json delete mode 100644 services/modules/transcription/remote/assembly_AI/package.json rename {services/modules/transcription/remote/assembly_AI => test/integration}/assembly.test.js (81%) diff --git a/package-lock.json b/package-lock.json index 3fe9ca4..52b523c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,9 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@types/axios": "^0.9.36", "cli-progress": "^3.12.0", + "dotenv": "^17.2.3", "electron": "^39.1.1", "express": "^5.1.0", "ffmpeg-static": "^5.2.0", @@ -149,6 +151,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/axios": { + "version": "0.9.36", + "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.9.36.tgz", + "integrity": "sha512-NLOpedx9o+rxo/X5ChbdiX6mS1atE4WHmEEIcR9NLenRVa5HoVjAvjafwU3FPTqnZEstpoqCaW7fagqSoTDNeg==", + "license": "MIT" + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -198,6 +206,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -584,6 +593,18 @@ "node": ">=0.3.1" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1824,6 +1845,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 14cba78..f85f30e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "dependencies": { + "@types/axios": "^0.9.36", "cli-progress": "^3.12.0", + "dotenv": "^17.2.3", "electron": "^39.1.1", "express": "^5.1.0", "ffmpeg-static": "^5.2.0", diff --git a/scripts/.gitkeep b/scripts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/scripts/commands.txt b/scripts/commands.txt deleted file mode 100644 index fc620fe..0000000 --- a/scripts/commands.txt +++ /dev/null @@ -1,5 +0,0 @@ -npx ts-node ./extract.ts /Users/mikehughes/Downloads/Testvideo/Kurzgesagt.mov -npx ts-node ./transcribe.ts ../storage/audio/Kurzgesagt.wav - -npx ts-node ./extract.ts /Users/mikehughes/Downloads/Testvideo/GitLabMeeting.mov -npx ts-node ./transcribe.ts ../storage/audio/GitLabMeeting.wav diff --git a/scripts/extract.ts b/scripts/extract.ts deleted file mode 100644 index 2d1c7a0..0000000 --- a/scripts/extract.ts +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env ts-node - -import { extractAudioFromVideo } from "../services/modules/extraction/ffmpegExtractor.ts"; - -const videoPath = process.argv[2]; - -if (!videoPath) { - console.error("Usage: ts-node extractAudio.ts "); - process.exit(1); -} - -(async () => { - try { - console.log(`Extracting audio from: ${videoPath}`); - - await extractAudioFromVideo(videoPath); // Call the extraction function (ffmpegExtractor.ts in services/modules/extraction) - - console.log("Audio extraction completed successfully."); - } catch (err) { - console.error("Audio extraction failed:", err); - process.exit(1); - } -})(); \ No newline at end of file diff --git a/scripts/transcribe.ts b/scripts/transcribe.ts deleted file mode 100644 index 55d91a5..0000000 --- a/scripts/transcribe.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { whisperLocal } from "../services/modules/transcription/local/whisperLocal.ts"; - -const audioPath = process.argv[2]; -if (!audioPath) { - console.error("Please provide an audio file path as argument."); - process.exit(1); -} - -const whisper = new whisperLocal(); - -(async () => { - try { - const text = await whisper.transcribe(audioPath); - console.log(text); - } catch (err) { - console.error("Transcription failed:", err); - } -})(); \ No newline at end of file diff --git a/services/modules/transcription/local/whisperLocal.ts b/services/modules/transcription-local/whisperLocal.ts similarity index 90% rename from services/modules/transcription/local/whisperLocal.ts rename to services/modules/transcription-local/whisperLocal.ts index e1923a0..1d331ac 100644 --- a/services/modules/transcription/local/whisperLocal.ts +++ b/services/modules/transcription-local/whisperLocal.ts @@ -5,7 +5,7 @@ import { fileURLToPath } from "url"; // To handle __dirname in ES modules const __filename = fileURLToPath(import.meta.url); // Get current file path const __dirname = path.dirname(__filename); // Get current directory path -const transcriptsDir = path.resolve(__dirname, "../../storage/transcriptions"); +const transcriptsDir = path.resolve(__dirname, "../../../storage/transcriptions"); export class whisperLocal { // is called by transcribe.ts @@ -26,7 +26,6 @@ export class whisperLocal { // is called by transcribe.ts async transcribe(audioPath: string): Promise { //asyncronous function to transcribe audio return new Promise((resolve, reject) => { - const transcriptsDir = path.resolve(__dirname, "../../../../storage/transcripts"); //storage directory for transcripts if (!fs.existsSync(transcriptsDir)) { //if transcripts directory does not exist, create it fs.mkdirSync(transcriptsDir, { recursive: true }); diff --git a/services/modules/transcription/remote/assembly_AI/assembly.js b/services/modules/transcription-remote/assembly.js similarity index 100% rename from services/modules/transcription/remote/assembly_AI/assembly.js rename to services/modules/transcription-remote/assembly.js diff --git a/services/modules/transcription/remote/assembly_AI/assembly.ts b/services/modules/transcription-remote/assembly.ts similarity index 100% rename from services/modules/transcription/remote/assembly_AI/assembly.ts rename to services/modules/transcription-remote/assembly.ts diff --git a/services/modules/transcription/local/whisper.cpp b/services/modules/transcription/local/whisper.cpp deleted file mode 160000 index 999a7e0..0000000 --- a/services/modules/transcription/local/whisper.cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 999a7e0cbf8484dc2cea1e9f855d6b39f34f7ae9 diff --git a/services/modules/transcription/remote/assembly_AI/package-lock.json b/services/modules/transcription/remote/assembly_AI/package-lock.json deleted file mode 100644 index 58c2913..0000000 --- a/services/modules/transcription/remote/assembly_AI/package-lock.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "name": "transcription", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "axios": "^1.13.2" - }, - "devDependencies": { - "@types/axios": "^0.9.36", - "@types/node": "^24.10.0" - } - }, - "node_modules/@types/axios": { - "version": "0.9.36", - "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.9.36.tgz", - "integrity": "sha512-NLOpedx9o+rxo/X5ChbdiX6mS1atE4WHmEEIcR9NLenRVa5HoVjAvjafwU3FPTqnZEstpoqCaW7fagqSoTDNeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", - "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - } - } -} diff --git a/services/modules/transcription/remote/assembly_AI/package.json b/services/modules/transcription/remote/assembly_AI/package.json deleted file mode 100644 index 6d24fe5..0000000 --- a/services/modules/transcription/remote/assembly_AI/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "dependencies": { - "axios": "^1.13.2" - }, - "devDependencies": { - "@types/axios": "^0.9.36", - "@types/node": "^24.10.0" - } -} diff --git a/services/modules/transcription/remote/assembly_AI/assembly.test.js b/test/integration/assembly.test.js similarity index 81% rename from services/modules/transcription/remote/assembly_AI/assembly.test.js rename to test/integration/assembly.test.js index 66ce753..46ac9ed 100644 --- a/services/modules/transcription/remote/assembly_AI/assembly.test.js +++ b/test/integration/assembly.test.js @@ -1,5 +1,5 @@ import 'dotenv/config'; -import assemblyModule from './assembly.ts'; +import assemblyModule from '../../services/modules/transcription-remote/assembly.ts'; // Test: URL passed as argument OR local file ./storage/audio/test.wav const audioPath = process.argv[2] || './storage/audio/test.wav'; From 9441699561a27e1ff06606f5c8335d3665dd1848 Mon Sep 17 00:00:00 2001 From: santa Date: Sun, 16 Nov 2025 14:46:19 +0100 Subject: [PATCH 06/37] if Pruefung fuer Datei Endung gefixt --- electron/main/renderer.js | 12 +++-- electron/main/script.js | 92 +++++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 46 deletions(-) diff --git a/electron/main/renderer.js b/electron/main/renderer.js index ad684ef..1bf23ea 100644 --- a/electron/main/renderer.js +++ b/electron/main/renderer.js @@ -16,15 +16,21 @@ uploadContainer.addEventListener("drop", (e) => { e.preventDefault() const files = e.dataTransfer.files const filePath = window.explorer.onFileDrop(files[0]) - var holdy = filePath + ""; - if(holdy.endsWith(".mp4") || holdy.endsWith(".mov") || holdy.endsWith(".avi") || holdy.endsWith( ".mkv")){ - console.log(filePath) + var holdy = String(filePath); + const lower = holdy.toLowerCase(); + const validExt = [".mp4", ".mov", ".avi", ".mkv"]; + + if(validExt.some(ext => lower.endsWith(ext))){ + console.log(filePath); const files1 = e.dataTransfer.files; handleFiles(files1); + }else{ + console.log('Video format invalid!'); } } catch (error) { console.log("Error in renderer.js with the listerner for the drop function"); + console.log(error); } diff --git a/electron/main/script.js b/electron/main/script.js index b947cdb..fac9960 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -6,7 +6,7 @@ manualUploadBtn.addEventListener('click', () => { } catch (error) { console.log("Error in manualBtn EventListener click"); } - + }); //function to check if one checkbox is at least klicked @@ -15,18 +15,24 @@ function checkBoxes() { const checkboxes = document.querySelectorAll('input[name="docFormat"]'); let isChecked = false; - checkboxes.forEach(function(checkbox){ - if(checkbox.checked){ + checkboxes.forEach(function (checkbox) { + if (checkbox.checked) { isChecked = true; } }); - if(isChecked){ + if (isChecked) { //Code to submit the video var pathTest = window.electronAPI.getFilePath(videoUpload.files[0]); - if(pathTest.endsWith(".mp4") || holdy.endsWith(".mov") || holdy.endsWith(".avi") || holdy.endsWith( ".mkv")){ - window.extractor.extract({inputVideoPath: pathTest, outputType:"wav"}) + + const lower = pathTest.toLowerCase(); + const validExt = [".mp4", ".mov", ".avi", ".mkv"]; + + if(validExt.some(ext => lower.endsWith(ext))){ + window.extractor.extract({ inputVideoPath: pathTest, outputType: "wav" }); } + + } else { //language only english at the moment alert('Please select at least one document type.'); @@ -34,43 +40,43 @@ function checkBoxes() { } catch (error) { console.log(error) } - -// mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./a.mp4", outputType:"wav"}) + + // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./a.mp4", outputType:"wav"}) } //language changing feature function changeLanguage(language) { - if (language === 'en') { - document.getElementById('title').textContent = 'Video to document'; - document.getElementById('h1').textContent = 'Video to document'; - document.getElementById('p1').textContent = 'Drag and drop video file'; - document.getElementById('fileName').textContent = 'No video chosen'; - document.getElementById('manualUploadBtn').textContent = 'Search video'; - document.getElementById('checkbox_group').textContent = 'Choose prefered document style:'; - document.getElementById('label_format').textContent = 'Meeting report'; - document.getElementById('label_summary').textContent = 'Summary with timestamps'; - document.getElementById('submitButton').textContent = 'Submit'; - } else if (language === 'de') { - document.getElementById('title').textContent = 'Video zu Dokument'; - document.getElementById('h1').textContent = 'Video zu Dokument'; - document.getElementById('p1').textContent = 'Video per Drag & Drop ablegen'; - document.getElementById('fileName').textContent = 'Kein Video ausgewaehlt'; - document.getElementById('manualUploadBtn').textContent = 'Video suchen'; - document.getElementById('checkbox_group').textContent = 'Bevorzugte Dokumentvarianten:'; - document.getElementById('label_format').textContent = 'Meeting Bericht'; - document.getElementById('label_summary').textContent = 'Zusammenfassung mit Zeitstempeln'; - document.getElementById('submitButton').textContent = 'Absenden'; - } else if(language == "in") { - document.getElementById('title').textContent = 'दस्तावेज़ के लिए वीडियो'; - document.getElementById('h1').textContent = 'दस्तावेज़ के लिए वीडियो'; - document.getElementById('p1').textContent = 'वीडियो फ़ाइल खींचें और छोड़ें'; - document.getElementById('fileName').textContent = 'कोई वीडियो नहीं चुना गया'; - document.getElementById('manualUploadBtn').textContent = 'वीडियो खोजें'; - document.getElementById('checkbox_group').textContent = 'पसंदीदा दस्तावेज़ शैली चुनें:'; - document.getElementById('label_format').textContent = 'बैठक रिपोर्ट'; - document.getElementById('label_summary').textContent = 'टाइमस्टैम्प के साथ सारांश'; - document.getElementById('submitButton').textContent = 'जमा करना'; - } + if (language === 'en') { + document.getElementById('title').textContent = 'Video to document'; + document.getElementById('h1').textContent = 'Video to document'; + document.getElementById('p1').textContent = 'Drag and drop video file'; + document.getElementById('fileName').textContent = 'No video chosen'; + document.getElementById('manualUploadBtn').textContent = 'Search video'; + document.getElementById('checkbox_group').textContent = 'Choose prefered document style:'; + document.getElementById('label_format').textContent = 'Meeting report'; + document.getElementById('label_summary').textContent = 'Summary with timestamps'; + document.getElementById('submitButton').textContent = 'Submit'; + } else if (language === 'de') { + document.getElementById('title').textContent = 'Video zu Dokument'; + document.getElementById('h1').textContent = 'Video zu Dokument'; + document.getElementById('p1').textContent = 'Video per Drag & Drop ablegen'; + document.getElementById('fileName').textContent = 'Kein Video ausgewaehlt'; + document.getElementById('manualUploadBtn').textContent = 'Video suchen'; + document.getElementById('checkbox_group').textContent = 'Bevorzugte Dokumentvarianten:'; + document.getElementById('label_format').textContent = 'Meeting Bericht'; + document.getElementById('label_summary').textContent = 'Zusammenfassung mit Zeitstempeln'; + document.getElementById('submitButton').textContent = 'Absenden'; + } else if (language == "in") { + document.getElementById('title').textContent = 'दस्तावेज़ के लिए वीडियो'; + document.getElementById('h1').textContent = 'दस्तावेज़ के लिए वीडियो'; + document.getElementById('p1').textContent = 'वीडियो फ़ाइल खींचें और छोड़ें'; + document.getElementById('fileName').textContent = 'कोई वीडियो नहीं चुना गया'; + document.getElementById('manualUploadBtn').textContent = 'वीडियो खोजें'; + document.getElementById('checkbox_group').textContent = 'पसंदीदा दस्तावेज़ शैली चुनें:'; + document.getElementById('label_format').textContent = 'बैठक रिपोर्ट'; + document.getElementById('label_summary').textContent = 'टाइमस्टैम्प के साथ सारांश'; + document.getElementById('submitButton').textContent = 'जमा करना'; + } } @@ -81,7 +87,7 @@ videoUpload.addEventListener('change', () => { } catch (error) { console.log("Error in manualBtn EventListener change"); } - + }); @@ -99,11 +105,11 @@ function handleFiles(files) { } catch (error) { console.log("Error in script.js handleFiles function"); } - + } //function to regulate the progress on the progressbar -function updateProgressBar(bar, value){ +function updateProgressBar(bar, value) { try { value = Math.round(value); bar.querySelector(".progress_fill").style.width = `${value}%`; @@ -111,5 +117,5 @@ function updateProgressBar(bar, value){ } catch (error) { console.log("Error in scripts.js updateProgressBar function"); } - + } \ No newline at end of file From 4dc53b9d5fd6c9d4078a695b7265093b1d278321 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 17 Nov 2025 18:00:04 +0100 Subject: [PATCH 07/37] implemented first version of the modular IPC system --- electron/main/preload.js | 30 ++++- main.js | 110 +++++++++++++++--- .../modules/extraction/ffmpegExtractor.js | 8 +- services/modules/utility/@startup.js | 3 + services/modules/utility/module-handler.js | 16 +++ 5 files changed, 149 insertions(+), 18 deletions(-) create mode 100644 services/modules/utility/module-handler.js diff --git a/electron/main/preload.js b/electron/main/preload.js index 355ace4..628e3f2 100644 --- a/electron/main/preload.js +++ b/electron/main/preload.js @@ -5,11 +5,39 @@ try { onFileDrop: (file) => webUtils.getPathForFile(file) }) contextBridge.exposeInMainWorld("extractor", { - extract: (file) => ipcRenderer.send("extract", file) + extract: (file) => { + +let q = // TODO get rid of this example code and have the actual json object be sent +{ + video: { + module: "extraction-video-to-audio", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio + inputVideoPath: file.inputVideoPath, // See script.js on line 27 for an example of what this should look like + outputType: file.outputType // The file format to be used for the audio output file, such as wav, mp3, flac and so on + }, + transcription:{ + module: "String" // The module name of the transcription model you want to use + }, + document:{ + module: "String", // The module name of the AI model you want to use to create the document + styles: [ // An array of all the document styles/prompts you want to have the document be processed with + { + prompt: "String", + } + ] + } +} + // ipcRenderer.send("file_submit", {module:"extraction-video-to-audio", parameter:file}) + ipcRenderer.send("file_submit", q) + } }) contextBridge.exposeInMainWorld("electronAPI", { getFilePath: (file) => {return webUtils.getPathForFile(file)} }) + + ipcRenderer.on("progress", (event, resp) => { + alert(`Finished step ${resp.curstep} of ${resp.totalsteps}`) + }) + ipcRenderer.on("error", (event, err) => {alert(err)}) } catch (error) { console.log("Error in preload.js"); } \ No newline at end of file diff --git a/main.js b/main.js index 1482f06..c0fc7ac 100644 --- a/main.js +++ b/main.js @@ -58,22 +58,106 @@ rl.on("line", data =>{ let mainWindow; function createWindow() { - mainWindow = new electron.BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - preload: `${mainDir}/electron/main/preload.js` - } - }); + mainWindow = new electron.BrowserWindow({ + width: 800, + height: 800, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + preload: `${mainDir}/electron/main/preload.js` + } + }); - mainWindow.loadFile('./electron/main/index.html'); + mainWindow.loadFile('./electron/main/index.html'); } electron.app.whenReady().then(createWindow); -electron.ipcMain.on("extract", (event, args) => { - mapFunctions.get("extraction-video-to-audio").function(args) -}) \ No newline at end of file +// electron.ipcMain.on("extract", (event, args) => { +// mapFunctions.get("extraction-video-to-audio").function(args) +// }) + +// setTimeout(() => { +// mainWindow.webContents.send("fuck", "worked uwu") +// }, 5000); + +electron.ipcMain.on("file_submit", async (event, args) => { + try { + + let curstep = 0 + let totalsteps = 2 + args.document.styles.length + + if(args.document.styles.length == 0) + throw new Error("At least one Document Style needed"); + + + console.log(args); + let audiopath = "" + let transcriptpath = "" + + // This code handles the Video to Audio extraction module call + await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => { + // console.log(resp); + audiopath = resp + curstep++ + mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) + }).catch(err => { + mainWindow.webContents.send("error", err) + return + }) + + + // TODO implement transcription module + // // This code handles the Audio to Text transcription module call + // await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => { + // console.log(resp); + // transcriptpath = resp + // curstep++ + // mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) + // }).catch(err => { + // mainWindow.webContents.send("error", err) + // return + // }) + + // TODO implement documentation module + // // This code handles the Text to Document processing module call + // for (let i = 0; i < args.document.styles.length; i++) { + // await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => { + // console.log(resp); + // transcriptpath = resp + // curstep++ + // mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) + // }).catch(err => { + // mainWindow.webContents.send("error", err) + // return + // }) + // } + + + } catch (error) { + console.log(error); + } +}) + + + +let q = +{ + video: { + module: "String", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio + inputVideoPath: "String", // See script.js on line 27 for an example of what this should look like + outputType: "String" // The file format to be used for the audio output file, such as wav, mp3, flac and so on + }, + transcription:{ + module: "String" // The module name of the transcription model you want to use + }, + document:{ + module: "String", // The module name of the AI model you want to use to create the document + styles: [ // An array of all the document styles/prompts you want to have the document be processed with + { + prompt: "String", + } + ] + } +} \ No newline at end of file diff --git a/services/modules/extraction/ffmpegExtractor.js b/services/modules/extraction/ffmpegExtractor.js index ffec9c0..acab307 100644 --- a/services/modules/extraction/ffmpegExtractor.js +++ b/services/modules/extraction/ffmpegExtractor.js @@ -32,11 +32,11 @@ module.exports = { hideCursor: true }); try { - // if (meta.url === `file://${process.argv[1]}`) { + return new Promise((resolve, reject) => { this.extractAudioFromVideo(parameter.inputVideoPath, progressBar, parameter.outputType) - .then(() => console.log('Audio extraction successful.')) + .then((resp) => resolve(resp)) .catch((err) => console.error(err)); - // } + }) } catch (error) { console.log(parameter.outputType); @@ -75,7 +75,7 @@ module.exports = { progressBar.update(100, { timemark: 'done' }); progressBar.stop(); console.log(`Extraction completed: ${outputAudioPath}`); - resolve(); + resolve(outputAudioPath); }) .on('error', (err) => { progressBar.stop(); diff --git a/services/modules/utility/@startup.js b/services/modules/utility/@startup.js index dcf64c8..e4e6f04 100644 --- a/services/modules/utility/@startup.js +++ b/services/modules/utility/@startup.js @@ -9,5 +9,8 @@ module.exports = { // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./a.mp4", outputType:"wav"}) // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./b.mp4", outputType:"wav"}) // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./b.mp4", outputType:"flac"}) + + // mapFunctions.get("ipc-handler").function("extraction-video-to-audio", {inputVideoPath:"./a.mp4", outputType:"flac"}) + } } \ No newline at end of file diff --git a/services/modules/utility/module-handler.js b/services/modules/utility/module-handler.js new file mode 100644 index 0000000..1e06115 --- /dev/null +++ b/services/modules/utility/module-handler.js @@ -0,0 +1,16 @@ +module.exports = { + name:"module-handler", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" + async function(module,parameter){ + return new Promise(async (resolve, reject) => { + if(mapFunctions.get(module) == undefined){ + reject("requested modules not found") + return + } + mapFunctions.get(module).function(parameter).then((result) => { + resolve(result) + }).catch((err) => { + reject(err) + }); + }) + } +} \ No newline at end of file From 8e7e0b50434c1523fcfeb598d9675e592b37e8b5 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Mon, 17 Nov 2025 21:16:50 +0100 Subject: [PATCH 08/37] Implement Gemini LLM module for document generation (first non tested prototype) --- services/modules/llm-gemini/gemini.js | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 services/modules/llm-gemini/gemini.js diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js new file mode 100644 index 0000000..3479e19 --- /dev/null +++ b/services/modules/llm-gemini/gemini.js @@ -0,0 +1,55 @@ +import fs from "fs"; +import { dirname } from "path"; +import { fileURLToPath } from "url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const { GoogleGenAI } = require("@google/genai"); + +const ai = new GoogleGenAI({ + apiKey: process.env.GOOGLE_API_KEY +}); + +const outputDir = `${__dirname}/../../../storage/documents`; +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + +module.exports = { + name: "llm-gemini", + type: "llm", + displayname: "Gemini LLM", + + async function(parameter) { + try { + console.log("Gemini LLM module invoked with parameters:", parameter); + + await this.createDocumentFromTranscript( + parameter.inputTranscriptPath, + parameter.documentType + ); + + } catch (error) { + console.error("Error in Gemini LLM module:", error); + } + }, + + createDocumentFromTranscript: async function(transcriptPath, documentType) { + try { + const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); + + const text = `${documentType}\n\n${transcript}`; + + const response = await ai.models.generateContent({ + model: "gemini-2.5-flash", + contents: text + }); + + const output = response.text ?? ""; + + fs.writeFileSync(`${outputDir}/test.md`, output, "utf8"); + console.log("Generated document written to test.md"); + } catch (error) { + console.error("Error generating content:", error); + } + } +}; \ No newline at end of file From a1d804f46356bcd2155bd05ae3148eae9e45801d Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Tue, 18 Nov 2025 19:16:51 +0100 Subject: [PATCH 09/37] Test created and changes to gemini.js file --- .../{document => llm-chat_gpt}/chatgpt.js | 0 services/modules/llm-gemini/gemini.js | 40 +++++++------- test/unit/gemini/documentType.txt | 39 ++++++++++++++ test/unit/gemini/test-gemini.js | 7 +++ test/unit/gemini/transcript.txt | 53 +++++++++++++++++++ 5 files changed, 121 insertions(+), 18 deletions(-) rename services/modules/{document => llm-chat_gpt}/chatgpt.js (100%) create mode 100644 test/unit/gemini/documentType.txt create mode 100644 test/unit/gemini/test-gemini.js create mode 100644 test/unit/gemini/transcript.txt diff --git a/services/modules/document/chatgpt.js b/services/modules/llm-chat_gpt/chatgpt.js similarity index 100% rename from services/modules/document/chatgpt.js rename to services/modules/llm-chat_gpt/chatgpt.js diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index 3479e19..eca9066 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -1,23 +1,22 @@ -import fs from "fs"; -import { dirname } from "path"; -import { fileURLToPath } from "url"; - -const __dirname = dirname(fileURLToPath(import.meta.url)); +const fs = require("fs"); +const path = require("path"); const { GoogleGenAI } = require("@google/genai"); +const outputDir = path.join(__dirname, "../../../storage/documents"); + +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY }); -const outputDir = `${__dirname}/../../../storage/documents`; -if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir, { recursive: true }); -} - module.exports = { name: "llm-gemini", type: "llm", displayname: "Gemini LLM", + description: "Generates documents using Google Gemini LLM", async function(parameter) { try { @@ -25,7 +24,8 @@ module.exports = { await this.createDocumentFromTranscript( parameter.inputTranscriptPath, - parameter.documentType + parameter.documentTypePath, + parameter.language ); } catch (error) { @@ -33,23 +33,27 @@ module.exports = { } }, - createDocumentFromTranscript: async function(transcriptPath, documentType) { + createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { try { const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); + const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); - const text = `${documentType}\n\n${transcript}`; + const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; const response = await ai.models.generateContent({ model: "gemini-2.5-flash", - contents: text + contents: promptText }); - const output = response.text ?? ""; + const output = response.text || ""; + + const outPath = path.join(outputDir, "test.md"); + fs.writeFileSync(outPath, output, "utf8"); + + console.log("Generated document written to:", outPath); - fs.writeFileSync(`${outputDir}/test.md`, output, "utf8"); - console.log("Generated document written to test.md"); } catch (error) { - console.error("Error generating content:", error); + console.error("Error generating Gemini content:", error); } } }; \ No newline at end of file diff --git a/test/unit/gemini/documentType.txt b/test/unit/gemini/documentType.txt new file mode 100644 index 0000000..f305f06 --- /dev/null +++ b/test/unit/gemini/documentType.txt @@ -0,0 +1,39 @@ + +**Goal:** Generate a structured meeting report (Markdown). **Output ONLY:** final .md. No meta. + +```json +{ + "FORMAT": "markdown", + + "STRUCTURE": { + "titlepage": ["title","date","start","end","duration","location","host","participants"], + "toc": "[section](#anchor) — HH:MM:SS", + "section": { + "h2": " — HH:MM:SS", + "summary": "1 sentence", + "key_points": "<=5 bullets, quotes optional", + "decisions": "list: text | owner | due", + "actions": "table: id | task | owner | due | status" + }, + "exec_summary": "3 short sentences", + "consolidated": ["decisions", "actions"], + "appendix": "optional" + }, + + "STYLE": { + "tone": "neutral, concise", + "ts_format": "HH:MM:SS", + "no_meta": true + }, + + "PROCESS": { + "timestamps": "use if present; else estimate minimal", + "speakers": "use labels; else Speaker X", + "long_transcripts": "chunk → summarize → merge", + "unclear": "UNKLAR:" + }, + + "JSON_OUTPUT_OPTIONAL": true, + + "PROMPT_SNIPPET": "Generate meeting report in markdown using STRUCTURE and STYLE. Output only the report." +} \ No newline at end of file diff --git a/test/unit/gemini/test-gemini.js b/test/unit/gemini/test-gemini.js new file mode 100644 index 0000000..9df6eb4 --- /dev/null +++ b/test/unit/gemini/test-gemini.js @@ -0,0 +1,7 @@ +const gemini = require("../../../services/modules/llm-gemini/gemini.js"); + +gemini.function({ + inputTranscriptPath: "./transcript.txt", + documentTypePath: "./documentType.txt", + language: "de" +}); \ No newline at end of file diff --git a/test/unit/gemini/transcript.txt b/test/unit/gemini/transcript.txt new file mode 100644 index 0000000..cae9726 --- /dev/null +++ b/test/unit/gemini/transcript.txt @@ -0,0 +1,53 @@ +Meeting Transcript - Video2Document Project +Date: November 18, 2025 +Attendees: Mike Hughes, Stefan Heyne, Alice Smith, Bob Johnson, Clara Nguyen + +[09:00 AM] Mike Hughes: Good morning, everyone. Let’s start the weekly project meeting for Video2Document. We have multiple points on the agenda today, including updates from each module, integration challenges, and the next sprint plan. + +[09:02 AM] Alice Smith: I’ve been working on the document formatting module. I’ve implemented support for markdown and PDF outputs. Still need to handle custom templates for clients. + +[09:05 AM] Bob Johnson: Video preprocessing is progressing. I’ve added support for multiple video codecs and automated audio extraction. I found that some videos require normalization before sending to the LLM. + +[09:08 AM] Stefan Heyne: For the LLM integration, I tested a few transcripts. Gemini handles summaries well, but we might need to tune prompts to get consistent headings and formatting. + +[09:12 AM] Clara Nguyen: On the storage side, I’ve configured S3 buckets for document storage. Permissions and versioning are set, but we still need to handle large batch uploads efficiently. + +[09:15 AM] Mike Hughes: Great updates. Let’s discuss some issues I noticed in the last integration test. First, audio extraction sometimes fails with videos longer than 20 minutes. Bob, any insights? + +[09:17 AM] Bob Johnson: Yes, I believe the FFmpeg timeout settings need adjustment. Also, some containerized environments lack the right codec libraries, causing failures. + +[09:20 AM] Stefan Heyne: On the LLM side, we noticed that very long transcripts lead to truncated outputs. We may need to split transcripts or chunk content intelligently before sending to Gemini. + +[09:22 AM] Alice Smith: For document formatting, longer outputs sometimes exceed the template limits. We need to implement pagination or splitting by sections. + +[09:25 AM] Clara Nguyen: For batch uploads, we can implement parallel processing with rate limiting to avoid S3 throttling. + +[09:28 AM] Mike Hughes: Action items from today’s discussion: +1. Bob: Adjust FFmpeg settings for long videos and document required codecs. +2. Stefan: Implement transcript chunking and test Gemini output for longer documents. +3. Alice: Add section splitting and pagination to document formatting. +4. Clara: Optimize batch upload process and test with larger datasets. + +[09:32 AM] Bob Johnson: Also, I propose adding logging for all preprocessing steps. This will help debug failed video conversions quickly. + +[09:35 AM] Stefan Heyne: Agreed. Logging in the LLM pipeline will also help identify failed content generations or prompt issues. + +[09:38 AM] Alice Smith: I can integrate logging hooks into the formatting module. Should include timestamped entries and file references. + +[09:40 AM] Clara Nguyen: I’ll add S3 upload logs and alerting for failed uploads. + +[09:42 AM] Mike Hughes: Perfect. Next sprint planning: we’ll prioritize long-video handling, chunked LLM summarization, and document formatting robustness. Everything else can follow in the subsequent sprint. + +[09:45 AM] Bob Johnson: I’ll provide a small script for testing various video lengths. Can be used to benchmark preprocessing times. + +[09:48 AM] Stefan Heyne: I’ll create example transcripts of different sizes to test Gemini LLM’s handling and summarize consistency. + +[09:50 AM] Alice Smith: I’ll create template variations for large documents and test rendering performance. + +[09:52 AM] Clara Nguyen: I’ll simulate batch uploads and stress-test the S3 storage setup. + +[09:55 AM] Mike Hughes: Excellent. Let’s reconvene next Wednesday for progress review. Make sure to push your updates to the repository beforehand. + +[09:57 AM] All: Agreed. + +Meeting adjourned at 10:00 AM. \ No newline at end of file From 75a454ad60d0a8d819a07002198a703ef30ca035 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Tue, 18 Nov 2025 19:38:33 +0100 Subject: [PATCH 10/37] Moved test files into integration folder as they use multiple different components --- test/{unit => integration}/gemini/documentType.txt | 0 test/{unit => integration}/gemini/test-gemini.js | 0 test/{unit => integration}/gemini/transcript.txt | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/{unit => integration}/gemini/documentType.txt (100%) rename test/{unit => integration}/gemini/test-gemini.js (100%) rename test/{unit => integration}/gemini/transcript.txt (100%) diff --git a/test/unit/gemini/documentType.txt b/test/integration/gemini/documentType.txt similarity index 100% rename from test/unit/gemini/documentType.txt rename to test/integration/gemini/documentType.txt diff --git a/test/unit/gemini/test-gemini.js b/test/integration/gemini/test-gemini.js similarity index 100% rename from test/unit/gemini/test-gemini.js rename to test/integration/gemini/test-gemini.js diff --git a/test/unit/gemini/transcript.txt b/test/integration/gemini/transcript.txt similarity index 100% rename from test/unit/gemini/transcript.txt rename to test/integration/gemini/transcript.txt From a178ccf30f8c1d879668267a3870d13eed4cb4ad Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Tue, 18 Nov 2025 19:53:19 +0100 Subject: [PATCH 11/37] Added comments to my code to make it more understandable --- services/modules/llm-gemini/gemini.js | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index eca9066..d28dda8 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -1,15 +1,15 @@ const fs = require("fs"); const path = require("path"); -const { GoogleGenAI } = require("@google/genai"); +const { GoogleGenAI } = require("@google/genai"); // Import Google Gemini AI SDK -const outputDir = path.join(__dirname, "../../../storage/documents"); +const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir, { recursive: true }); + fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist } -const ai = new GoogleGenAI({ - apiKey: process.env.GOOGLE_API_KEY +const ai = new GoogleGenAI({ + apiKey: process.env.GOOGLE_API_KEY // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" }); module.exports = { @@ -22,10 +22,10 @@ module.exports = { try { console.log("Gemini LLM module invoked with parameters:", parameter); - await this.createDocumentFromTranscript( - parameter.inputTranscriptPath, - parameter.documentTypePath, - parameter.language + await this.createDocumentFromTranscript( //Call the function to create document with transcript, document type and language + parameter.inputTranscriptPath, // Path to input transcript file + parameter.documentTypePath, // Path to document type file which is chosen in the front end by the user + parameter.language // Language for the document which is chosen in the front end by the user ); } catch (error) { @@ -33,7 +33,7 @@ module.exports = { } }, - createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { + createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English try { const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); @@ -41,14 +41,14 @@ module.exports = { const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; const response = await ai.models.generateContent({ - model: "gemini-2.5-flash", - contents: promptText + model: "gemini-2.5-flash", // Specify the Gemini model to use + contents: promptText // Input prompt for content generation }); - const output = response.text || ""; + const output = response.text || ""; // Get generated text from response or default to empty string (if null) - const outPath = path.join(outputDir, "test.md"); - fs.writeFileSync(outPath, output, "utf8"); + const outPath = path.join(outputDir, "test.md"); // Output file path & name TO BE DONE to make dynamic out of input transcript name + fs.writeFileSync(outPath, output, "utf8"); // Write output to file console.log("Generated document written to:", outPath); From 455147a41b49388c61cadad674f587e6152801c6 Mon Sep 17 00:00:00 2001 From: santa Date: Thu, 20 Nov 2025 10:15:11 +0100 Subject: [PATCH 12/37] Summarizer Tool erstellt zur zusammenfassung der vom TranskriptionTool kommenden json --- .../jsonTools/transcriptionSummarizer.js | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 services/modules/jsonTools/transcriptionSummarizer.js diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js new file mode 100644 index 0000000..dae3537 --- /dev/null +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -0,0 +1,123 @@ +// Prepare output directory (always storage/transcriptionSummaries under project root) +const outputDir = `${__dirname}/../../../storage/transcriptionSummaries`; +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + +module.exports = { + name: "summarize-transcription", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" + type: "transcription", // value used to differentiate each module to order them in the UI + displayname: "Summarizer", // The displayname used within the UI + async function(args) { + let inputJson = args.json; + + // JSON parsen + if (typeof inputJson === "string") { + try { + inputJson = JSON.parse(inputJson); + } catch (e) { + console.log("Invalid JSON in summarize-transcription"); + return { error: "Invalid JSON" }; + } + } + + const words = inputJson.words; + if (!Array.isArray(words)) { + return { error: "No words Array found" }; + } + + const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? + const ABBREVIATIONS = new Set(["z.B.", "bzw.", "u.a.", "Dr.", "Mr.", "Mrs.", "Prof.", "etc."]); //TODO weitere Ergaenzen + + const result = []; + let currentSentence = ""; + let currentSpeaker = null; + let startTime = null; + let endTime = null; + + for (const w of words) { + if (!currentSpeaker) currentSpeaker = w.speaker; + if (startTime === null) startTime = w.start; + endTime = w.end; + + //speaker changing + if (currentSpeaker !== w.speaker && currentSentence) { + const lastEntry = result[result.length - 1]; + if (lastEntry && lastEntry.speaker === currentSpeaker) { + lastEntry.sentence += " " + currentSentence; + lastEntry.end = endTime; + } else { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + } + currentSentence = ""; + startTime = w.start; + } + currentSpeaker = w.speaker; + currentSentence += (currentSentence ? " " : "") + w.text; //sentence beginning or not + const lastWord = w.text.trim(); + const lastChar = lastWord.slice(-1); + const isAbbreviation = ABBREVIATIONS.has(lastWord); + + //sentence ending + if (ENDINGS.includes(lastChar) && !isAbbreviation) { + const lastEntry = result[result.length - 1]; + if (lastEntry && lastEntry.speaker === currentSpeaker) { + lastEntry.sentence += " " + currentSentence; + lastEntry.end = endTime; + } else { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + } + currentSentence = ""; + startTime = null; + endTime = null; + currentSpeaker = null; + } + } + + // safe last sentence + if (currentSentence) { + const lastEntry = result[result.length - 1]; + if (lastEntry && lastEntry.speaker === currentSpeaker) { + lastEntry.sentence += " " + currentSentence; + lastEntry.end = endTime; + } else { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + } + } + + // Output as Text + const output = result.map(r => + `Sprecher ${r.speaker} [${r.start.toFixed(2)} - ${r.end.toFixed(2)}]: ${r.sentence}` + ); + + // Output on cosole + //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); + + try { + const jsonPath = path.join(outputDir, "transcription_result.json"); + fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); + + const txtPath = path.join(outputDir, "transcription_result.txt"); + fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); + + console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); + } catch (err) { + console.error("Error saving Summary:", err); + } + } +} From 97b571b7f961682ea10d7ca6fdbbf8032c7465f5 Mon Sep 17 00:00:00 2001 From: santa Date: Thu, 20 Nov 2025 11:51:34 +0100 Subject: [PATCH 13/37] Einbindung des Summarizer --- electron/main/preload.js | 3 +++ main.js | 7 ++++++- .../modules/jsonTools/transcriptionSummarizer.js | 12 +++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/electron/main/preload.js b/electron/main/preload.js index ec7ff05..e2353c7 100644 --- a/electron/main/preload.js +++ b/electron/main/preload.js @@ -12,6 +12,9 @@ try { contextBridge.exposeInMainWorld("electronAPI", { getFilePath: (file) => {return webUtils.getPathForFile(file)} }) + contextBridge.exposeInMainWorld("summarizer", { + runFile: (file) => ipcRenderer.send("summarize-transcription", file) + }); } catch (error) { console.log("Error in preload.js"); } diff --git a/main.js b/main.js index 1482f06..38137b6 100644 --- a/main.js +++ b/main.js @@ -76,4 +76,9 @@ electron.app.whenReady().then(createWindow); electron.ipcMain.on("extract", (event, args) => { mapFunctions.get("extraction-video-to-audio").function(args) -}) \ No newline at end of file +}) + +electron.ipcMain.on("summarize-transcription", (event, args) => { + mapFunctions.get("summarize-transcription").function(args); +}); + diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index dae3537..ea1025c 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -6,11 +6,21 @@ if (!fs.existsSync(outputDir)) { module.exports = { name: "summarize-transcription", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" - type: "transcription", // value used to differentiate each module to order them in the UI + type: "summarizer", // value used to differentiate each module to order them in the UI displayname: "Summarizer", // The displayname used within the UI async function(args) { let inputJson = args.json; + //JSON Path + if (args.jsonPath) { + try { + const raw = fs.readFileSync(args.jsonPath, "utf-8"); + inputJson = JSON.parse(raw); + } catch (e) { + console.error("Failed to load JSON from file:", e); + return { error: "Could not read JSON from file path." }; + } + } // JSON parsen if (typeof inputJson === "string") { try { From b87bfd444df687bb371442bc22dd3d3fd7bd9684 Mon Sep 17 00:00:00 2001 From: santa Date: Thu, 20 Nov 2025 13:27:15 +0100 Subject: [PATCH 14/37] Test erstellt --- .../jsonTools/transcriptionSummarizer.js | 4 +- .../modules/transcription-remote/assembly.js | 132 +- test/integration/testFile.json | 12320 ++++++++++++++++ .../transcriptionSummarizerTest.js | 12 + 4 files changed, 12460 insertions(+), 8 deletions(-) create mode 100644 test/integration/testFile.json create mode 100644 test/integration/transcriptionSummarizerTest.js diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index ea1025c..0003b52 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -1,3 +1,5 @@ +const fs = require("fs"); + // Prepare output directory (always storage/transcriptionSummaries under project root) const outputDir = `${__dirname}/../../../storage/transcriptionSummaries`; if (!fs.existsSync(outputDir)) { @@ -30,7 +32,7 @@ module.exports = { return { error: "Invalid JSON" }; } } - + console.log(inputJson); const words = inputJson.words; if (!Array.isArray(words)) { return { error: "No words Array found" }; diff --git a/services/modules/transcription-remote/assembly.js b/services/modules/transcription-remote/assembly.js index 3b28dad..bf72e1f 100644 --- a/services/modules/transcription-remote/assembly.js +++ b/services/modules/transcription-remote/assembly.js @@ -1,8 +1,126 @@ -module.exports = { - name:"assembly", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" - type:"transcription", // value used to differentiate each module to order them in the UI - displayname:"Assembly", // The displayname used within the UI - async function(parameter){ - // TODO add code to actually process the audio file +//require('dotenv').config(); +//const axios = require('axios'); +//const fs = require('fs'); +const path = require('path'); + +const API_KEY = process.env.ASSEMBLYAI_API_KEY; +const BASE_URL = 'https://api.assemblyai.com/v2'; + +//---------------------------------------------------Upload audio--------------------------------------------------- + +async function uploadAudio(audioPath) { + const audioData = fs.readFileSync(audioPath); + + const response = await axios.post(`${BASE_URL}/upload`, audioData, { + headers: { + authorization: API_KEY, + 'content-type': 'application/octet-stream' } -} \ No newline at end of file + }); + + return response.data.upload_url; +} + +////---------------------------------------------------Extract session id--------------------------------------------------- + +function getSessionId(inputPath) { + try { + const parsed = new URL(inputPath); + const base = path.basename(parsed.pathname); + return base.replace(/\.[^.]+$/, ''); + } catch { + return path.basename(inputPath, path.extname(inputPath)); + } +} + +//---------------------------------------------------Create transcript--------------------------------------------------- + +async function createTranscript(audioUrl) { + const response = await axios.post( + `${BASE_URL}/transcript`, + { + audio_url: audioUrl, + speaker_labels: true, + language_detection: true + }, + { + headers: { + authorization: API_KEY, + 'content-type': 'application/json' + } + } + ); + + return response.data.id; +} + +//---------------------------------------------------Poll transcript--------------------------------------------------- + +async function pollTranscript(transcriptId) { + while (true) { + const response = await axios.get(`${BASE_URL}/transcript/${transcriptId}`, { + headers: { authorization: API_KEY } + }); + + const status = response.data.status; + + if (status === 'completed') return response.data; + if (status === 'error') throw new Error(`Transcription failed: ${response.data.error}`); + + await new Promise(res => setTimeout(res, 3000)); + } +} + +//---------------------------------------------------Save transcript--------------------------------------------------- + +function saveTranscript(transcript, sessionId) { + const outputDir = path.join(__dirname, '../../../storage/transcripts'); + + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + const outputPath = path.join(outputDir, `${sessionId}.json`); + fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2)); + + console.log(`Transcript saved: ${outputPath}`); +} + +//---------------------------------------------------Modul--------------------------------------------------- + +module.exports = { + name: 'assembly', + type: 'transcription', + displayname: 'AssemblyAI', + + run: async (audioFileName) => { + try { + // audioFileName ist nur "datei.mp3" + const audioPath = path.join( + __dirname, + '../../../storage/audio', + audioFileName + ); + + let audioUrl; + + if (/^https?:\/\//i.test(audioFileName)) { + audioUrl = audioFileName; + } else { + if (!fs.existsSync(audioPath)) { + throw new Error(`Audio file not found: ${audioPath}`); + } + audioUrl = await uploadAudio(audioPath); + } + + const transcriptId = await createTranscript(audioUrl); + const transcript = await pollTranscript(transcriptId); + + const sessionId = getSessionId(audioFileName); + saveTranscript(transcript, sessionId); + + } catch (error) { + console.error('Transcription error:', error.message); + } + } +}; diff --git a/test/integration/testFile.json b/test/integration/testFile.json new file mode 100644 index 0000000..a1de5d5 --- /dev/null +++ b/test/integration/testFile.json @@ -0,0 +1,12320 @@ +{ + "id": "e5c8854a-3ac4-4069-a0f4-3a0ef4d3dd57", + "language_model": "assemblyai_default", + "acoustic_model": "assemblyai_default", + "language_code": "en", + "speech_understanding": null, + "translated_texts": null, + "status": "completed", + "audio_url": "https://github.com/AssemblyAI-Examples/audio-examples/raw/main/20230607_me_canadian_wildfires.mp3", + "text": "Smoke from hundreds of wildfires in Canada is triggering air quality alerts throughout the US Skylines from Maine to Maryland to Minnesota are gray and smoggy. And in some places, the air quality warnings include the warning to stay inside. We wanted to better understand what's happening here and why, so we called Peter DeCarlo, an associate professor in the Department of Environmental Health and Engineering at Johns Hopkins University. Good morning, Professor. Good morning. So what is it about the conditions right now that have caused this round of wildfires to affect so many people so far away? Well, there's a couple of things. The season has been pretty dry already, and then the fact that we're getting hit in the US is because there's a couple weather systems that are essentially channeling the smoke from those Canadian wildfires through Pennsylvania into the mid Atlantic and the Northeast and kind of just dropping the smoke there. So what is it in this haze that makes it harmful? And I'm assuming it is harmful. It is, it is. The levels outside right now in Baltimore are considered unhealthy. And most of that is due to what's called particulate matter, which are tiny particles, microscopic, smaller than the width of your hair, that can get into your lungs and impact your respiratory system, your cardiovascular system, and even your neurological, your brain. What makes this particularly harmful? Is it the volume of particulate? Is it something in particular? What is it exactly? Can you just drill down on that a little bit more? Yeah. So the concentration of particulate matter, I was looking at some of the monitors that we have was reaching levels of what are, in science speak, 150 micrograms per meter cubed, which is more than 10 times what the annual average should be in about four times higher than what you're supposed to have on a 24 hour average. And so the concentrations of these particles in the air are just much, much, much higher than we typically see. And exposure to those high levels can lead to a host of health problems. And who is most vulnerable? I noticed that in New York City, for example, they're canceling outdoor activities. And so here it is in the early days of summer and they have to keep all the kids inside. So who tends to be vulnerable in a situation like this? It's the youngest. So children, obviously, whose bodies are still developing, the elderly who are, you know, their bodies are more in decline and they're more susceptible to the health impacts of breathing, the poor air quality. And then people who have pre existing health conditions, people with respiratory conditions or heart conditions, can be triggered by high levels of air pollution. Could this get worse? That's a good question. I mean, I think if in some areas it's much worse than others and it just depends on kind of where the smoke is concentrated. I think New York has some of the higher concentrations right now, but that's going to change as that air moves away from the New York area. But over the course of the next few days, we will see different areas being hit at different times with the highest concentrations. I was going to ask you about. More fires start burning. I don't expect the concentrations to go up too much higher. I was going to ask you how and you started to answer this, but how much longer could this last? Forgive me if I'm asking you to speculate, but what do you think? Well, I think the fires are going to burn for a little bit longer. But the key for us in the US Is the weather system changing. Right now it's the weather systems that are pulling that air into our Mid Atlantic and Northeast region. As those weather systems change and shift, we'll see that smoke going elsewhere and not impact us in this region as much. I think that's going to be the defining factor. I think the next couple days we're going to see a shift in that weather pattern and start to push the smoke away from where we are. And finally, with the impacts of climate change, we are seeing more wildfires. Will we be seeing more of these kinds of wide ranging air quality consequences or circumstances? I mean, that is one of the predictions for climate change. Looking into the future, the fire season is starting earlier and lasting longer and we're seeing more frequent fires. So yeah, this is probably something that we'll be seeing more, more frequently. This tends to be much more of an issue in the western U.S. so the eastern U.S. getting hit right now is a little bit new. But yeah, I think with climate change moving forward, this is something that is going to happen more frequently. That's Peter DeCarlo, associate professor in the Department of Environmental Health and Engineering at Johns Hopkins University. Professor DeCarlo, thanks so much for joining us and sharing this expertise with us. Thank you for having me.", + "words": [ + { + "text": "Smoke", + "start": 240, + "end": 640, + "confidence": 0.90152997, + "speaker": "A" + }, + { + "text": "from", + "start": 640, + "end": 1000, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "hundreds", + "start": 1000, + "end": 1480, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "of", + "start": 1480, + "end": 1640, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "wildfires", + "start": 1640, + "end": 2320, + "confidence": 0.99970704, + "speaker": "A" + }, + { + "text": "in", + "start": 2320, + "end": 2480, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "Canada", + "start": 2480, + "end": 2800, + "confidence": 1, + "speaker": "A" + }, + { + "text": "is", + "start": 3120, + "end": 3440, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "triggering", + "start": 3440, + "end": 3920, + "confidence": 0.9998779, + "speaker": "A" + }, + { + "text": "air", + "start": 3920, + "end": 4160, + "confidence": 1, + "speaker": "A" + }, + { + "text": "quality", + "start": 4160, + "end": 4640, + "confidence": 0.78100586, + "speaker": "A" + }, + { + "text": "alerts", + "start": 4640, + "end": 5120, + "confidence": 0.9013672, + "speaker": "A" + }, + { + "text": "throughout", + "start": 5120, + "end": 5480, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "the", + "start": 5480, + "end": 5680, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "US", + "start": 5680, + "end": 6000, + "confidence": 0.9770508, + "speaker": "A" + }, + { + "text": "Skylines", + "start": 6480, + "end": 7280, + "confidence": 0.9996338, + "speaker": "A" + }, + { + "text": "from", + "start": 7280, + "end": 7440, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "Maine", + "start": 7440, + "end": 7920, + "confidence": 0.84106445, + "speaker": "A" + }, + { + "text": "to", + "start": 8000, + "end": 8280, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "Maryland", + "start": 8280, + "end": 8680, + "confidence": 0.9978841, + "speaker": "A" + }, + { + "text": "to", + "start": 8680, + "end": 8920, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "Minnesota", + "start": 8920, + "end": 9640, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "are", + "start": 9640, + "end": 9920, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "gray", + "start": 9920, + "end": 10200, + "confidence": 0.7348633, + "speaker": "A" + }, + { + "text": "and", + "start": 10200, + "end": 10400, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "smoggy.", + "start": 10400, + "end": 11040, + "confidence": 0.9984131, + "speaker": "A" + }, + { + "text": "And", + "start": 11040, + "end": 11360, + "confidence": 0.97021484, + "speaker": "A" + }, + { + "text": "in", + "start": 11360, + "end": 11560, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "some", + "start": 11560, + "end": 11760, + "confidence": 1, + "speaker": "A" + }, + { + "text": "places,", + "start": 11760, + "end": 12120, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "the", + "start": 12120, + "end": 12320, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "air", + "start": 12320, + "end": 12560, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "quality", + "start": 12560, + "end": 12960, + "confidence": 1, + "speaker": "A" + }, + { + "text": "warnings", + "start": 12960, + "end": 13400, + "confidence": 0.99820966, + "speaker": "A" + }, + { + "text": "include", + "start": 13400, + "end": 13680, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "the", + "start": 13680, + "end": 13960, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "warning", + "start": 13960, + "end": 14240, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "to", + "start": 14240, + "end": 14480, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "stay", + "start": 14480, + "end": 14800, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "inside.", + "start": 14880, + "end": 15520, + "confidence": 1, + "speaker": "A" + }, + { + "text": "We", + "start": 15919, + "end": 16199, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "wanted", + "start": 16199, + "end": 16400, + "confidence": 0.99243164, + "speaker": "A" + }, + { + "text": "to", + "start": 16400, + "end": 16520, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "better", + "start": 16520, + "end": 16720, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "understand", + "start": 16720, + "end": 17040, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "what's", + "start": 17040, + "end": 17440, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "happening", + "start": 17440, + "end": 17760, + "confidence": 0.8527832, + "speaker": "A" + }, + { + "text": "here", + "start": 17760, + "end": 18000, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "and", + "start": 18000, + "end": 18200, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "why,", + "start": 18200, + "end": 18440, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "so", + "start": 18440, + "end": 18640, + "confidence": 0.9863281, + "speaker": "A" + }, + { + "text": "we", + "start": 18640, + "end": 18760, + "confidence": 0.9838867, + "speaker": "A" + }, + { + "text": "called", + "start": 18760, + "end": 18920, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "Peter", + "start": 18920, + "end": 19240, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "DeCarlo,", + "start": 19240, + "end": 19920, + "confidence": 0.88265, + "speaker": "A" + }, + { + "text": "an", + "start": 20000, + "end": 20280, + "confidence": 0.9604492, + "speaker": "A" + }, + { + "text": "associate", + "start": 20280, + "end": 20720, + "confidence": 1, + "speaker": "A" + }, + { + "text": "professor", + "start": 20720, + "end": 21160, + "confidence": 1, + "speaker": "A" + }, + { + "text": "in", + "start": 21160, + "end": 21320, + "confidence": 0.99316406, + "speaker": "A" + }, + { + "text": "the", + "start": 21320, + "end": 21480, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "Department", + "start": 21480, + "end": 21760, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "of", + "start": 21760, + "end": 22040, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Environmental", + "start": 22040, + "end": 22720, + "confidence": 0.9987793, + "speaker": "A" + }, + { + "text": "Health", + "start": 22720, + "end": 22960, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "and", + "start": 22960, + "end": 23200, + "confidence": 0.9951172, + "speaker": "A" + }, + { + "text": "Engineering", + "start": 23200, + "end": 23680, + "confidence": 1, + "speaker": "A" + }, + { + "text": "at", + "start": 23680, + "end": 23920, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "Johns", + "start": 23920, + "end": 24360, + "confidence": 0.9733887, + "speaker": "A" + }, + { + "text": "Hopkins", + "start": 24360, + "end": 24840, + "confidence": 1, + "speaker": "A" + }, + { + "text": "University.", + "start": 24840, + "end": 25200, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Good", + "start": 25520, + "end": 25800, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "morning,", + "start": 25800, + "end": 26000, + "confidence": 1, + "speaker": "A" + }, + { + "text": "Professor.", + "start": 26000, + "end": 26560, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Good", + "start": 28060, + "end": 28260, + "confidence": 0.96484375, + "speaker": "B" + }, + { + "text": "morning.", + "start": 28260, + "end": 28620, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "So", + "start": 29100, + "end": 29500, + "confidence": 0.6220703, + "speaker": "A" + }, + { + "text": "what", + "start": 29660, + "end": 29940, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "is", + "start": 29940, + "end": 30100, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "it", + "start": 30100, + "end": 30260, + "confidence": 0.9941406, + "speaker": "A" + }, + { + "text": "about", + "start": 30260, + "end": 30500, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "the", + "start": 30500, + "end": 30740, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "conditions", + "start": 30740, + "end": 31260, + "confidence": 1, + "speaker": "A" + }, + { + "text": "right", + "start": 31260, + "end": 31660, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "now", + "start": 31660, + "end": 32060, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "that", + "start": 32140, + "end": 32420, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "have", + "start": 32420, + "end": 32620, + "confidence": 0.99121094, + "speaker": "A" + }, + { + "text": "caused", + "start": 32620, + "end": 32980, + "confidence": 0.9707031, + "speaker": "A" + }, + { + "text": "this", + "start": 32980, + "end": 33260, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "round", + "start": 33260, + "end": 33500, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 33500, + "end": 33740, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "wildfires", + "start": 33740, + "end": 34540, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "to", + "start": 34540, + "end": 34700, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "affect", + "start": 34700, + "end": 35140, + "confidence": 0.9914551, + "speaker": "A" + }, + { + "text": "so", + "start": 35140, + "end": 35380, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "many", + "start": 35380, + "end": 35580, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "people", + "start": 35580, + "end": 35900, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "so", + "start": 36300, + "end": 36580, + "confidence": 1, + "speaker": "A" + }, + { + "text": "far", + "start": 36580, + "end": 36780, + "confidence": 1, + "speaker": "A" + }, + { + "text": "away?", + "start": 36780, + "end": 37100, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "Well,", + "start": 39100, + "end": 39380, + "confidence": 0.9394531, + "speaker": "B" + }, + { + "text": "there's", + "start": 39380, + "end": 39580, + "confidence": 0.98844403, + "speaker": "B" + }, + { + "text": "a", + "start": 39580, + "end": 39660, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "couple", + "start": 39660, + "end": 39860, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "of", + "start": 39860, + "end": 40020, + "confidence": 0.94628906, + "speaker": "B" + }, + { + "text": "things.", + "start": 40020, + "end": 40300, + "confidence": 0.9428711, + "speaker": "B" + }, + { + "text": "The", + "start": 41020, + "end": 41340, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "season", + "start": 41340, + "end": 41620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "has", + "start": 41620, + "end": 41820, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "been", + "start": 41820, + "end": 41940, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "pretty", + "start": 41940, + "end": 42140, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "dry", + "start": 42140, + "end": 42340, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "already,", + "start": 42340, + "end": 42620, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "and", + "start": 43020, + "end": 43340, + "confidence": 0.9794922, + "speaker": "B" + }, + { + "text": "then", + "start": 43340, + "end": 43660, + "confidence": 0.9892578, + "speaker": "B" + }, + { + "text": "the", + "start": 43660, + "end": 43940, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "fact", + "start": 43940, + "end": 44100, + "confidence": 1, + "speaker": "B" + }, + { + "text": "that", + "start": 44100, + "end": 44260, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "we're", + "start": 44260, + "end": 44500, + "confidence": 0.8828125, + "speaker": "B" + }, + { + "text": "getting", + "start": 44500, + "end": 44740, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hit", + "start": 44740, + "end": 44980, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "in", + "start": 44980, + "end": 45140, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 45140, + "end": 45300, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "US", + "start": 45300, + "end": 45580, + "confidence": 0.9863281, + "speaker": "B" + }, + { + "text": "is", + "start": 46140, + "end": 46460, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "because", + "start": 46460, + "end": 46700, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "there's", + "start": 46700, + "end": 47020, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "a", + "start": 47020, + "end": 47100, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "couple", + "start": 47100, + "end": 47340, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "weather", + "start": 47340, + "end": 47660, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "systems", + "start": 47660, + "end": 47980, + "confidence": 0.9987793, + "speaker": "B" + }, + { + "text": "that", + "start": 47980, + "end": 48060, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "are", + "start": 48060, + "end": 48180, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "essentially", + "start": 48180, + "end": 48580, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "channeling", + "start": 48580, + "end": 49020, + "confidence": 0.970459, + "speaker": "B" + }, + { + "text": "the", + "start": 49020, + "end": 49140, + "confidence": 0.98828125, + "speaker": "B" + }, + { + "text": "smoke", + "start": 49140, + "end": 49380, + "confidence": 0.9682617, + "speaker": "B" + }, + { + "text": "from", + "start": 49380, + "end": 49540, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "those", + "start": 49540, + "end": 49700, + "confidence": 0.96875, + "speaker": "B" + }, + { + "text": "Canadian", + "start": 49700, + "end": 50100, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "wildfires", + "start": 50100, + "end": 50780, + "confidence": 0.9993164, + "speaker": "B" + }, + { + "text": "through", + "start": 51260, + "end": 51620, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "Pennsylvania", + "start": 51620, + "end": 52340, + "confidence": 0.9989692, + "speaker": "B" + }, + { + "text": "into", + "start": 52340, + "end": 52500, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 52500, + "end": 52660, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "mid", + "start": 52660, + "end": 52820, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "Atlantic", + "start": 52820, + "end": 53180, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "and", + "start": 53180, + "end": 53300, + "confidence": 0.52978516, + "speaker": "B" + }, + { + "text": "the", + "start": 53300, + "end": 53420, + "confidence": 0.9785156, + "speaker": "B" + }, + { + "text": "Northeast", + "start": 53420, + "end": 53860, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "and", + "start": 53860, + "end": 54140, + "confidence": 0.8803711, + "speaker": "B" + }, + { + "text": "kind", + "start": 54220, + "end": 54460, + "confidence": 0.8515625, + "speaker": "B" + }, + { + "text": "of", + "start": 54460, + "end": 54580, + "confidence": 0.98779297, + "speaker": "B" + }, + { + "text": "just", + "start": 54580, + "end": 54740, + "confidence": 0.98583984, + "speaker": "B" + }, + { + "text": "dropping", + "start": 54740, + "end": 55140, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "the", + "start": 55140, + "end": 55260, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "smoke", + "start": 55260, + "end": 55540, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "there.", + "start": 55540, + "end": 55820, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "So", + "start": 56590, + "end": 56670, + "confidence": 0.8666992, + "speaker": "A" + }, + { + "text": "what", + "start": 56670, + "end": 56790, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "is", + "start": 56790, + "end": 56950, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "it", + "start": 56950, + "end": 57110, + "confidence": 0.9814453, + "speaker": "A" + }, + { + "text": "in", + "start": 57110, + "end": 57270, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "this", + "start": 57270, + "end": 57470, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "haze", + "start": 57470, + "end": 57910, + "confidence": 0.9347331, + "speaker": "A" + }, + { + "text": "that", + "start": 57910, + "end": 58110, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "makes", + "start": 58110, + "end": 58430, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "it", + "start": 58510, + "end": 58830, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "harmful?", + "start": 58830, + "end": 59310, + "confidence": 0.9998372, + "speaker": "A" + }, + { + "text": "And", + "start": 59310, + "end": 59470, + "confidence": 0.71435547, + "speaker": "A" + }, + { + "text": "I'm", + "start": 59470, + "end": 59670, + "confidence": 0.98307294, + "speaker": "A" + }, + { + "text": "assuming", + "start": 59670, + "end": 59990, + "confidence": 1, + "speaker": "A" + }, + { + "text": "it", + "start": 59990, + "end": 60110, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "is", + "start": 60110, + "end": 60230, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "harmful.", + "start": 60230, + "end": 60670, + "confidence": 0.91780597, + "speaker": "A" + }, + { + "text": "It", + "start": 62350, + "end": 62630, + "confidence": 0.9238281, + "speaker": "B" + }, + { + "text": "is,", + "start": 62630, + "end": 62870, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "it", + "start": 62870, + "end": 63110, + "confidence": 0.8666992, + "speaker": "B" + }, + { + "text": "is.", + "start": 63110, + "end": 63350, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "The", + "start": 63350, + "end": 63590, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "levels", + "start": 63590, + "end": 64030, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "outside", + "start": 64030, + "end": 64430, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "right", + "start": 64510, + "end": 64790, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "now", + "start": 64790, + "end": 64950, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "in", + "start": 64950, + "end": 65110, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "Baltimore", + "start": 65110, + "end": 65590, + "confidence": 0.9998047, + "speaker": "B" + }, + { + "text": "are", + "start": 65590, + "end": 65750, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "considered", + "start": 65750, + "end": 66070, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "unhealthy.", + "start": 66070, + "end": 66750, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "And", + "start": 67790, + "end": 68110, + "confidence": 0.67822266, + "speaker": "B" + }, + { + "text": "most", + "start": 68110, + "end": 68310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 68310, + "end": 68470, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "that", + "start": 68470, + "end": 68630, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "is", + "start": 68630, + "end": 68790, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "due", + "start": 68790, + "end": 68990, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "to", + "start": 68990, + "end": 69270, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "what's", + "start": 69270, + "end": 69630, + "confidence": 0.9916992, + "speaker": "B" + }, + { + "text": "called", + "start": 69630, + "end": 69750, + "confidence": 1, + "speaker": "B" + }, + { + "text": "particulate", + "start": 69750, + "end": 70310, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "matter,", + "start": 70310, + "end": 70470, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "which", + "start": 70470, + "end": 70670, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "are", + "start": 70670, + "end": 70870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "tiny", + "start": 70870, + "end": 71190, + "confidence": 1, + "speaker": "B" + }, + { + "text": "particles,", + "start": 71190, + "end": 71630, + "confidence": 0.7578125, + "speaker": "B" + }, + { + "text": "microscopic,", + "start": 72110, + "end": 72910, + "confidence": 0.97957355, + "speaker": "B" + }, + { + "text": "smaller", + "start": 72910, + "end": 73310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "than", + "start": 73310, + "end": 73390, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 73390, + "end": 73470, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "width", + "start": 73470, + "end": 73670, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 73670, + "end": 73950, + "confidence": 0.98095703, + "speaker": "B" + }, + { + "text": "your", + "start": 73950, + "end": 74270, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hair,", + "start": 74270, + "end": 74670, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "that", + "start": 75230, + "end": 75550, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "can", + "start": 75550, + "end": 75750, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "get", + "start": 75750, + "end": 75910, + "confidence": 1, + "speaker": "B" + }, + { + "text": "into", + "start": 75910, + "end": 76070, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "your", + "start": 76070, + "end": 76230, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "lungs", + "start": 76230, + "end": 76550, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 76550, + "end": 76830, + "confidence": 0.9145508, + "speaker": "B" + }, + { + "text": "impact", + "start": 76910, + "end": 77270, + "confidence": 1, + "speaker": "B" + }, + { + "text": "your", + "start": 77270, + "end": 77590, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "respiratory", + "start": 77590, + "end": 78150, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "system,", + "start": 78150, + "end": 78470, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "your", + "start": 78470, + "end": 78710, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "cardiovascular", + "start": 78710, + "end": 79470, + "confidence": 0.99958146, + "speaker": "B" + }, + { + "text": "system,", + "start": 79470, + "end": 79790, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 80430, + "end": 80710, + "confidence": 0.99121094, + "speaker": "B" + }, + { + "text": "even", + "start": 80710, + "end": 80910, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "your", + "start": 80910, + "end": 81230, + "confidence": 0.53027344, + "speaker": "B" + }, + { + "text": "neurological,", + "start": 81310, + "end": 82030, + "confidence": 0.99768066, + "speaker": "B" + }, + { + "text": "your", + "start": 82030, + "end": 82230, + "confidence": 0.9746094, + "speaker": "B" + }, + { + "text": "brain.", + "start": 82230, + "end": 82590, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "What", + "start": 83630, + "end": 83790, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "makes", + "start": 83790, + "end": 83990, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "this", + "start": 83990, + "end": 84190, + "confidence": 0.9423828, + "speaker": "A" + }, + { + "text": "particularly", + "start": 84190, + "end": 84990, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "harmful?", + "start": 84990, + "end": 85550, + "confidence": 0.9998372, + "speaker": "A" + }, + { + "text": "Is", + "start": 85550, + "end": 85750, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "it", + "start": 85750, + "end": 85870, + "confidence": 0.9946289, + "speaker": "A" + }, + { + "text": "the", + "start": 85870, + "end": 86110, + "confidence": 0.59228516, + "speaker": "A" + }, + { + "text": "volume", + "start": 86670, + "end": 87150, + "confidence": 0.8741862, + "speaker": "A" + }, + { + "text": "of", + "start": 87150, + "end": 87390, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "particulate?", + "start": 87390, + "end": 88030, + "confidence": 0.8585612, + "speaker": "A" + }, + { + "text": "Is", + "start": 88030, + "end": 88230, + "confidence": 0.9892578, + "speaker": "A" + }, + { + "text": "it", + "start": 88230, + "end": 88390, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "something", + "start": 88390, + "end": 88590, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "in", + "start": 88590, + "end": 88790, + "confidence": 0.96435547, + "speaker": "A" + }, + { + "text": "particular?", + "start": 88790, + "end": 89070, + "confidence": 0.97753906, + "speaker": "A" + }, + { + "text": "What", + "start": 89390, + "end": 89670, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "is", + "start": 89670, + "end": 89790, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "it", + "start": 89790, + "end": 89910, + "confidence": 0.9946289, + "speaker": "A" + }, + { + "text": "exactly?", + "start": 89910, + "end": 90350, + "confidence": 0.92545575, + "speaker": "A" + }, + { + "text": "Can", + "start": 90350, + "end": 90510, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "you", + "start": 90510, + "end": 90590, + "confidence": 1, + "speaker": "A" + }, + { + "text": "just", + "start": 90590, + "end": 90790, + "confidence": 0.98095703, + "speaker": "A" + }, + { + "text": "drill", + "start": 90790, + "end": 91070, + "confidence": 1, + "speaker": "A" + }, + { + "text": "down", + "start": 91070, + "end": 91190, + "confidence": 1, + "speaker": "A" + }, + { + "text": "on", + "start": 91190, + "end": 91350, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "that", + "start": 91350, + "end": 91510, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "a", + "start": 91510, + "end": 91630, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "little", + "start": 91630, + "end": 91750, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "bit", + "start": 91750, + "end": 91910, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "more?", + "start": 91910, + "end": 92190, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "Yeah.", + "start": 93550, + "end": 93950, + "confidence": 0.9145508, + "speaker": "B" + }, + { + "text": "So", + "start": 93950, + "end": 94150, + "confidence": 0.5620117, + "speaker": "B" + }, + { + "text": "the", + "start": 94150, + "end": 94310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "concentration", + "start": 94310, + "end": 94830, + "confidence": 1, + "speaker": "B" + }, + { + "text": "of", + "start": 94830, + "end": 95070, + "confidence": 1, + "speaker": "B" + }, + { + "text": "particulate", + "start": 95070, + "end": 95630, + "confidence": 0.99934894, + "speaker": "B" + }, + { + "text": "matter,", + "start": 95630, + "end": 95950, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "I", + "start": 96350, + "end": 96590, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "was", + "start": 96590, + "end": 96710, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "looking", + "start": 96710, + "end": 96870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "at", + "start": 96870, + "end": 96990, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "some", + "start": 96990, + "end": 97110, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "of", + "start": 97110, + "end": 97230, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 97230, + "end": 97310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "monitors", + "start": 97310, + "end": 97630, + "confidence": 0.99934894, + "speaker": "B" + }, + { + "text": "that", + "start": 97630, + "end": 97750, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "we", + "start": 97750, + "end": 97910, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "have", + "start": 97910, + "end": 98190, + "confidence": 0.94677734, + "speaker": "B" + }, + { + "text": "was", + "start": 98270, + "end": 98550, + "confidence": 0.9838867, + "speaker": "B" + }, + { + "text": "reaching", + "start": 98550, + "end": 98869, + "confidence": 1, + "speaker": "B" + }, + { + "text": "levels", + "start": 98869, + "end": 99150, + "confidence": 1, + "speaker": "B" + }, + { + "text": "of", + "start": 99150, + "end": 99270, + "confidence": 0.9921875, + "speaker": "B" + }, + { + "text": "what", + "start": 99270, + "end": 99430, + "confidence": 0.88671875, + "speaker": "B" + }, + { + "text": "are,", + "start": 99430, + "end": 99710, + "confidence": 0.97509766, + "speaker": "B" + }, + { + "text": "in", + "start": 100910, + "end": 101190, + "confidence": 0.9838867, + "speaker": "B" + }, + { + "text": "science", + "start": 101190, + "end": 101430, + "confidence": 0.99731445, + "speaker": "B" + }, + { + "text": "speak,", + "start": 101430, + "end": 101710, + "confidence": 0.8635254, + "speaker": "B" + }, + { + "text": "150", + "start": 101710, + "end": 102350, + "confidence": 0.98551, + "speaker": "B" + }, + { + "text": "micrograms", + "start": 102350, + "end": 102910, + "confidence": 0.9963379, + "speaker": "B" + }, + { + "text": "per", + "start": 102910, + "end": 103030, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "meter", + "start": 103030, + "end": 103350, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "cubed,", + "start": 103350, + "end": 103670, + "confidence": 0.9954427, + "speaker": "B" + }, + { + "text": "which", + "start": 103670, + "end": 103830, + "confidence": 1, + "speaker": "B" + }, + { + "text": "is", + "start": 103830, + "end": 104110, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "more", + "start": 104270, + "end": 104550, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 104550, + "end": 104790, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "10", + "start": 104790, + "end": 105110, + "confidence": 1, + "speaker": "B" + }, + { + "text": "times", + "start": 105110, + "end": 105390, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "what", + "start": 105390, + "end": 105590, + "confidence": 0.99365234, + "speaker": "B" + }, + { + "text": "the", + "start": 105590, + "end": 105750, + "confidence": 1, + "speaker": "B" + }, + { + "text": "annual", + "start": 105750, + "end": 106110, + "confidence": 1, + "speaker": "B" + }, + { + "text": "average", + "start": 106110, + "end": 106510, + "confidence": 1, + "speaker": "B" + }, + { + "text": "should", + "start": 106510, + "end": 106790, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "be", + "start": 106790, + "end": 107150, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "in", + "start": 107390, + "end": 107670, + "confidence": 0.87841797, + "speaker": "B" + }, + { + "text": "about", + "start": 107670, + "end": 107950, + "confidence": 0.9711914, + "speaker": "B" + }, + { + "text": "four", + "start": 109110, + "end": 109270, + "confidence": 0.98046875, + "speaker": "B" + }, + { + "text": "times", + "start": 109270, + "end": 109550, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "higher", + "start": 109550, + "end": 109790, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 109790, + "end": 109950, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "what", + "start": 109950, + "end": 110070, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "you're", + "start": 110070, + "end": 110270, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "supposed", + "start": 110270, + "end": 110510, + "confidence": 0.998291, + "speaker": "B" + }, + { + "text": "to", + "start": 110510, + "end": 110670, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "have", + "start": 110670, + "end": 110950, + "confidence": 1, + "speaker": "B" + }, + { + "text": "on", + "start": 111350, + "end": 111670, + "confidence": 1, + "speaker": "B" + }, + { + "text": "a", + "start": 111670, + "end": 111910, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "24", + "start": 111910, + "end": 112390, + "confidence": 1, + "speaker": "B" + }, + { + "text": "hour", + "start": 112390, + "end": 112630, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "average.", + "start": 112630, + "end": 113110, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "And", + "start": 113350, + "end": 113710, + "confidence": 0.8989258, + "speaker": "B" + }, + { + "text": "so", + "start": 113710, + "end": 114070, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 114070, + "end": 114390, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "concentrations", + "start": 114390, + "end": 115110, + "confidence": 0.99816895, + "speaker": "B" + }, + { + "text": "of", + "start": 115110, + "end": 115230, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "these", + "start": 115230, + "end": 115390, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "particles", + "start": 115390, + "end": 115710, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "in", + "start": 115710, + "end": 115830, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 115830, + "end": 115950, + "confidence": 0.98583984, + "speaker": "B" + }, + { + "text": "air", + "start": 115950, + "end": 116230, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "are", + "start": 116550, + "end": 116870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "just", + "start": 116870, + "end": 117190, + "confidence": 0.9838867, + "speaker": "B" + }, + { + "text": "much,", + "start": 117350, + "end": 117710, + "confidence": 0.9873047, + "speaker": "B" + }, + { + "text": "much,", + "start": 117710, + "end": 117950, + "confidence": 1, + "speaker": "B" + }, + { + "text": "much", + "start": 117950, + "end": 118150, + "confidence": 1, + "speaker": "B" + }, + { + "text": "higher", + "start": 118150, + "end": 118350, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 118350, + "end": 118630, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "we", + "start": 118630, + "end": 118910, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "typically", + "start": 118910, + "end": 119270, + "confidence": 1, + "speaker": "B" + }, + { + "text": "see.", + "start": 119270, + "end": 119590, + "confidence": 1, + "speaker": "B" + }, + { + "text": "And", + "start": 119750, + "end": 120110, + "confidence": 0.98291016, + "speaker": "B" + }, + { + "text": "exposure", + "start": 120110, + "end": 120710, + "confidence": 0.9996745, + "speaker": "B" + }, + { + "text": "to", + "start": 120710, + "end": 120910, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "those", + "start": 120910, + "end": 121110, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "high", + "start": 121110, + "end": 121350, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "levels", + "start": 121350, + "end": 121710, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "can", + "start": 121710, + "end": 121870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "lead", + "start": 121870, + "end": 122030, + "confidence": 1, + "speaker": "B" + }, + { + "text": "to", + "start": 122030, + "end": 122150, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 122150, + "end": 122270, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "host", + "start": 122270, + "end": 122430, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 122430, + "end": 122630, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "health", + "start": 122630, + "end": 122870, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "problems.", + "start": 122870, + "end": 123350, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "And", + "start": 123430, + "end": 123710, + "confidence": 0.94970703, + "speaker": "A" + }, + { + "text": "who", + "start": 123710, + "end": 123870, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "is", + "start": 123870, + "end": 124070, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "most", + "start": 124070, + "end": 124310, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "vulnerable?", + "start": 124310, + "end": 124949, + "confidence": 1, + "speaker": "A" + }, + { + "text": "I", + "start": 124949, + "end": 125230, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "noticed", + "start": 125230, + "end": 125510, + "confidence": 0.882487, + "speaker": "A" + }, + { + "text": "that", + "start": 125510, + "end": 125630, + "confidence": 0.97998047, + "speaker": "A" + }, + { + "text": "in", + "start": 125630, + "end": 125750, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "New", + "start": 125750, + "end": 125870, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "York", + "start": 125870, + "end": 126030, + "confidence": 1, + "speaker": "A" + }, + { + "text": "City,", + "start": 126030, + "end": 126190, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "for", + "start": 126190, + "end": 126350, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "example,", + "start": 126350, + "end": 126750, + "confidence": 0.96435547, + "speaker": "A" + }, + { + "text": "they're", + "start": 126750, + "end": 127190, + "confidence": 0.9485677, + "speaker": "A" + }, + { + "text": "canceling", + "start": 127190, + "end": 127790, + "confidence": 0.87597656, + "speaker": "A" + }, + { + "text": "outdoor", + "start": 127790, + "end": 128190, + "confidence": 0.9984131, + "speaker": "A" + }, + { + "text": "activities.", + "start": 128190, + "end": 128670, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "And", + "start": 128670, + "end": 128990, + "confidence": 0.9458008, + "speaker": "A" + }, + { + "text": "so", + "start": 128990, + "end": 129230, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "here", + "start": 129230, + "end": 129390, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "it", + "start": 129390, + "end": 129510, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "is", + "start": 129510, + "end": 129630, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "in", + "start": 129630, + "end": 129910, + "confidence": 0.94921875, + "speaker": "A" + }, + { + "text": "the", + "start": 130070, + "end": 130470, + "confidence": 0.85595703, + "speaker": "A" + }, + { + "text": "early", + "start": 130550, + "end": 130830, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "days", + "start": 130830, + "end": 130990, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 130990, + "end": 131150, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "summer", + "start": 131150, + "end": 131390, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "and", + "start": 131390, + "end": 131510, + "confidence": 0.9663086, + "speaker": "A" + }, + { + "text": "they", + "start": 131510, + "end": 131630, + "confidence": 0.9296875, + "speaker": "A" + }, + { + "text": "have", + "start": 131630, + "end": 131750, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "to", + "start": 131750, + "end": 131830, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "keep", + "start": 131830, + "end": 131950, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "all", + "start": 131950, + "end": 132110, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "the", + "start": 132110, + "end": 132230, + "confidence": 0.9902344, + "speaker": "A" + }, + { + "text": "kids", + "start": 132230, + "end": 132470, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "inside.", + "start": 132470, + "end": 132950, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "So", + "start": 132950, + "end": 133350, + "confidence": 0.95214844, + "speaker": "A" + }, + { + "text": "who", + "start": 133350, + "end": 133670, + "confidence": 1, + "speaker": "A" + }, + { + "text": "tends", + "start": 133670, + "end": 133950, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "to", + "start": 133950, + "end": 134110, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "be", + "start": 134110, + "end": 134270, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "vulnerable", + "start": 134270, + "end": 134670, + "confidence": 1, + "speaker": "A" + }, + { + "text": "in", + "start": 134670, + "end": 134830, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "a", + "start": 134830, + "end": 134990, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "situation", + "start": 134990, + "end": 135430, + "confidence": 1, + "speaker": "A" + }, + { + "text": "like", + "start": 135510, + "end": 135750, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "this?", + "start": 135750, + "end": 135990, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "It's", + "start": 137610, + "end": 137930, + "confidence": 0.9005534, + "speaker": "B" + }, + { + "text": "the", + "start": 137930, + "end": 138250, + "confidence": 0.5307617, + "speaker": "B" + }, + { + "text": "youngest.", + "start": 138250, + "end": 138810, + "confidence": 0.9851074, + "speaker": "B" + }, + { + "text": "So", + "start": 138810, + "end": 139090, + "confidence": 0.6489258, + "speaker": "B" + }, + { + "text": "children,", + "start": 139090, + "end": 139330, + "confidence": 1, + "speaker": "B" + }, + { + "text": "obviously,", + "start": 139330, + "end": 140010, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "whose", + "start": 140890, + "end": 141450, + "confidence": 0.79467773, + "speaker": "B" + }, + { + "text": "bodies", + "start": 141450, + "end": 141730, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "are", + "start": 141730, + "end": 141850, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "still", + "start": 141850, + "end": 141970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "developing,", + "start": 141970, + "end": 142450, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 142450, + "end": 142730, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "elderly", + "start": 142730, + "end": 143250, + "confidence": 1, + "speaker": "B" + }, + { + "text": "who", + "start": 143250, + "end": 143530, + "confidence": 0.89160156, + "speaker": "B" + }, + { + "text": "are,", + "start": 143530, + "end": 143810, + "confidence": 0.70458984, + "speaker": "B" + }, + { + "text": "you", + "start": 143810, + "end": 144010, + "confidence": 0.5307617, + "speaker": "B" + }, + { + "text": "know,", + "start": 144010, + "end": 144170, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "their", + "start": 144170, + "end": 144370, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "bodies", + "start": 144370, + "end": 144570, + "confidence": 0.9996745, + "speaker": "B" + }, + { + "text": "are", + "start": 144570, + "end": 144690, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "more", + "start": 144690, + "end": 144850, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "in", + "start": 144850, + "end": 144970, + "confidence": 0.96435547, + "speaker": "B" + }, + { + "text": "decline", + "start": 144970, + "end": 145250, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "and", + "start": 145250, + "end": 145410, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "they're", + "start": 145410, + "end": 145610, + "confidence": 0.9921875, + "speaker": "B" + }, + { + "text": "more", + "start": 145610, + "end": 145730, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "susceptible", + "start": 145730, + "end": 146250, + "confidence": 0.99960935, + "speaker": "B" + }, + { + "text": "to", + "start": 146250, + "end": 146450, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 146450, + "end": 146570, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "health", + "start": 146570, + "end": 146770, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "impacts", + "start": 146770, + "end": 147250, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "of", + "start": 147250, + "end": 147530, + "confidence": 0.95751953, + "speaker": "B" + }, + { + "text": "breathing,", + "start": 147690, + "end": 148130, + "confidence": 0.95426434, + "speaker": "B" + }, + { + "text": "the", + "start": 148130, + "end": 148410, + "confidence": 0.7241211, + "speaker": "B" + }, + { + "text": "poor", + "start": 148490, + "end": 148810, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "air", + "start": 148810, + "end": 148970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "quality.", + "start": 148970, + "end": 149450, + "confidence": 1, + "speaker": "B" + }, + { + "text": "And", + "start": 150570, + "end": 150850, + "confidence": 0.8666992, + "speaker": "B" + }, + { + "text": "then", + "start": 150850, + "end": 151050, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "people", + "start": 151050, + "end": 151290, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "who", + "start": 151290, + "end": 151490, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "have", + "start": 151490, + "end": 151610, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "pre", + "start": 151610, + "end": 151770, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "existing", + "start": 151770, + "end": 152169, + "confidence": 0.98828125, + "speaker": "B" + }, + { + "text": "health", + "start": 152169, + "end": 152369, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "conditions,", + "start": 152369, + "end": 152650, + "confidence": 0.9987793, + "speaker": "B" + }, + { + "text": "people", + "start": 152650, + "end": 152850, + "confidence": 0.9707031, + "speaker": "B" + }, + { + "text": "with", + "start": 152850, + "end": 153010, + "confidence": 0.9951172, + "speaker": "B" + }, + { + "text": "respiratory", + "start": 153010, + "end": 153410, + "confidence": 0.9978841, + "speaker": "B" + }, + { + "text": "conditions", + "start": 153410, + "end": 153770, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "or", + "start": 153770, + "end": 153970, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "heart", + "start": 153970, + "end": 154130, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "conditions,", + "start": 154130, + "end": 154490, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "can", + "start": 154490, + "end": 154690, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "be", + "start": 154690, + "end": 154850, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "triggered", + "start": 154850, + "end": 155210, + "confidence": 1, + "speaker": "B" + }, + { + "text": "by", + "start": 155210, + "end": 155370, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "high", + "start": 155370, + "end": 155610, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "levels", + "start": 155610, + "end": 155850, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "of", + "start": 155850, + "end": 155970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "air", + "start": 155970, + "end": 156170, + "confidence": 1, + "speaker": "B" + }, + { + "text": "pollution.", + "start": 156170, + "end": 156650, + "confidence": 1, + "speaker": "B" + }, + { + "text": "Could", + "start": 157450, + "end": 157770, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "this", + "start": 157770, + "end": 158010, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "get", + "start": 158010, + "end": 158210, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "worse?", + "start": 158210, + "end": 158650, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "That's", + "start": 162170, + "end": 162490, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 162490, + "end": 162610, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "good", + "start": 162610, + "end": 162770, + "confidence": 1, + "speaker": "B" + }, + { + "text": "question.", + "start": 162770, + "end": 163050, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "I", + "start": 163130, + "end": 163410, + "confidence": 0.93896484, + "speaker": "B" + }, + { + "text": "mean,", + "start": 163410, + "end": 163570, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "I", + "start": 163570, + "end": 163690, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "think", + "start": 163690, + "end": 163850, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "if", + "start": 163850, + "end": 164170, + "confidence": 0.98779297, + "speaker": "B" + }, + { + "text": "in", + "start": 165260, + "end": 165380, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "some", + "start": 165380, + "end": 165540, + "confidence": 1, + "speaker": "B" + }, + { + "text": "areas", + "start": 165540, + "end": 165820, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "it's", + "start": 165900, + "end": 166220, + "confidence": 0.99820966, + "speaker": "B" + }, + { + "text": "much", + "start": 166220, + "end": 166340, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "worse", + "start": 166340, + "end": 166540, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 166540, + "end": 166660, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "others", + "start": 166660, + "end": 166860, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 166860, + "end": 167180, + "confidence": 0.97314453, + "speaker": "B" + }, + { + "text": "it", + "start": 167180, + "end": 167460, + "confidence": 0.99121094, + "speaker": "B" + }, + { + "text": "just", + "start": 167460, + "end": 167620, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "depends", + "start": 167620, + "end": 167980, + "confidence": 0.90201825, + "speaker": "B" + }, + { + "text": "on", + "start": 167980, + "end": 168180, + "confidence": 0.9951172, + "speaker": "B" + }, + { + "text": "kind", + "start": 168180, + "end": 168340, + "confidence": 0.79785156, + "speaker": "B" + }, + { + "text": "of", + "start": 168340, + "end": 168500, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "where", + "start": 168500, + "end": 168700, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 168700, + "end": 168860, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "smoke", + "start": 168860, + "end": 169140, + "confidence": 0.9503581, + "speaker": "B" + }, + { + "text": "is", + "start": 169140, + "end": 169340, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "concentrated.", + "start": 169340, + "end": 170140, + "confidence": 0.99990237, + "speaker": "B" + }, + { + "text": "I", + "start": 171020, + "end": 171300, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "think", + "start": 171300, + "end": 171460, + "confidence": 1, + "speaker": "B" + }, + { + "text": "New", + "start": 171460, + "end": 171620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "York", + "start": 171620, + "end": 171900, + "confidence": 1, + "speaker": "B" + }, + { + "text": "has", + "start": 171980, + "end": 172260, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "some", + "start": 172260, + "end": 172420, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 172420, + "end": 172540, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 172540, + "end": 172660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "higher", + "start": 172660, + "end": 172860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "concentrations", + "start": 172860, + "end": 173540, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "right", + "start": 173540, + "end": 173700, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "now,", + "start": 173700, + "end": 173860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "but", + "start": 173860, + "end": 174020, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "that's", + "start": 174020, + "end": 174220, + "confidence": 0.9983724, + "speaker": "B" + }, + { + "text": "going", + "start": 174220, + "end": 174340, + "confidence": 0.7973633, + "speaker": "B" + }, + { + "text": "to", + "start": 174340, + "end": 174460, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "change", + "start": 174460, + "end": 174620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "as", + "start": 174620, + "end": 174820, + "confidence": 0.99121094, + "speaker": "B" + }, + { + "text": "that", + "start": 174820, + "end": 174980, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "air", + "start": 174980, + "end": 175180, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "moves", + "start": 175180, + "end": 175500, + "confidence": 1, + "speaker": "B" + }, + { + "text": "away", + "start": 175500, + "end": 175660, + "confidence": 1, + "speaker": "B" + }, + { + "text": "from", + "start": 175660, + "end": 175860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 175860, + "end": 175980, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "New", + "start": 175980, + "end": 176100, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "York", + "start": 176100, + "end": 176300, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "area.", + "start": 176300, + "end": 176620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "But", + "start": 177100, + "end": 177380, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "over", + "start": 177380, + "end": 177540, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 177540, + "end": 177660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "course", + "start": 177660, + "end": 177780, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 177780, + "end": 177900, + "confidence": 0.82958984, + "speaker": "B" + }, + { + "text": "the", + "start": 177900, + "end": 177980, + "confidence": 0.9667969, + "speaker": "B" + }, + { + "text": "next", + "start": 177980, + "end": 178100, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "few", + "start": 178100, + "end": 178300, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "days,", + "start": 178300, + "end": 178500, + "confidence": 1, + "speaker": "B" + }, + { + "text": "we", + "start": 178500, + "end": 178660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "will", + "start": 178660, + "end": 178860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "see", + "start": 178860, + "end": 179180, + "confidence": 1, + "speaker": "B" + }, + { + "text": "different", + "start": 179580, + "end": 179940, + "confidence": 1, + "speaker": "B" + }, + { + "text": "areas", + "start": 179940, + "end": 180220, + "confidence": 1, + "speaker": "B" + }, + { + "text": "being", + "start": 180220, + "end": 180539, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hit", + "start": 180539, + "end": 180940, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "at", + "start": 180940, + "end": 181220, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "different", + "start": 181220, + "end": 181460, + "confidence": 1, + "speaker": "B" + }, + { + "text": "times", + "start": 181460, + "end": 181820, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "with", + "start": 181980, + "end": 182260, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 182260, + "end": 182380, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "highest", + "start": 182380, + "end": 182660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "concentrations.", + "start": 182660, + "end": 183420, + "confidence": 0.998291, + "speaker": "B" + }, + { + "text": "I", + "start": 183740, + "end": 183980, + "confidence": 0.9140625, + "speaker": "A" + }, + { + "text": "was", + "start": 183980, + "end": 184100, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "going", + "start": 184100, + "end": 184220, + "confidence": 0.96484375, + "speaker": "A" + }, + { + "text": "to", + "start": 184220, + "end": 184300, + "confidence": 0.9897461, + "speaker": "A" + }, + { + "text": "ask", + "start": 184300, + "end": 184380, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "you", + "start": 184380, + "end": 184460, + "confidence": 0.86083984, + "speaker": "A" + }, + { + "text": "about.", + "start": 184460, + "end": 184660, + "confidence": 0.84472656, + "speaker": "A" + }, + { + "text": "More", + "start": 184660, + "end": 184900, + "confidence": 0.57958984, + "speaker": "B" + }, + { + "text": "fires", + "start": 184900, + "end": 185220, + "confidence": 0.8249512, + "speaker": "B" + }, + { + "text": "start", + "start": 185220, + "end": 185380, + "confidence": 0.94628906, + "speaker": "B" + }, + { + "text": "burning.", + "start": 185380, + "end": 185660, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "I", + "start": 185660, + "end": 185860, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "don't", + "start": 185860, + "end": 186060, + "confidence": 0.9998372, + "speaker": "B" + }, + { + "text": "expect", + "start": 186060, + "end": 186300, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 186940, + "end": 187220, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "concentrations", + "start": 187220, + "end": 187780, + "confidence": 0.99890137, + "speaker": "B" + }, + { + "text": "to", + "start": 187780, + "end": 187900, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "go", + "start": 187900, + "end": 188020, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "up", + "start": 188020, + "end": 188300, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "too", + "start": 188300, + "end": 188580, + "confidence": 0.98583984, + "speaker": "B" + }, + { + "text": "much", + "start": 188580, + "end": 188740, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "higher.", + "start": 188740, + "end": 189020, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "I", + "start": 189100, + "end": 189340, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "was", + "start": 189340, + "end": 189420, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "going", + "start": 189420, + "end": 189540, + "confidence": 0.97998047, + "speaker": "A" + }, + { + "text": "to", + "start": 189540, + "end": 189660, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "ask", + "start": 189660, + "end": 189780, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "you", + "start": 189780, + "end": 189940, + "confidence": 0.9819336, + "speaker": "A" + }, + { + "text": "how", + "start": 189940, + "end": 190100, + "confidence": 0.7294922, + "speaker": "A" + }, + { + "text": "and", + "start": 190100, + "end": 190260, + "confidence": 0.94677734, + "speaker": "A" + }, + { + "text": "you", + "start": 190260, + "end": 190420, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "started", + "start": 190420, + "end": 190620, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "to", + "start": 190620, + "end": 190780, + "confidence": 0.9404297, + "speaker": "A" + }, + { + "text": "answer", + "start": 190780, + "end": 190980, + "confidence": 0.96809894, + "speaker": "A" + }, + { + "text": "this,", + "start": 190980, + "end": 191140, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "but", + "start": 191140, + "end": 191420, + "confidence": 0.9013672, + "speaker": "A" + }, + { + "text": "how", + "start": 191420, + "end": 191700, + "confidence": 1, + "speaker": "A" + }, + { + "text": "much", + "start": 191700, + "end": 191940, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "longer", + "start": 191940, + "end": 192420, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "could", + "start": 192420, + "end": 192700, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "this", + "start": 192700, + "end": 192940, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "last?", + "start": 192940, + "end": 193260, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Forgive", + "start": 193420, + "end": 193820, + "confidence": 0.99934894, + "speaker": "A" + }, + { + "text": "me", + "start": 193820, + "end": 193900, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "if", + "start": 193900, + "end": 193980, + "confidence": 0.98095703, + "speaker": "A" + }, + { + "text": "I'm", + "start": 193980, + "end": 194140, + "confidence": 0.9920247, + "speaker": "A" + }, + { + "text": "asking", + "start": 194140, + "end": 194300, + "confidence": 1, + "speaker": "A" + }, + { + "text": "you", + "start": 194300, + "end": 194380, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "to", + "start": 194380, + "end": 194500, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "speculate,", + "start": 194500, + "end": 194900, + "confidence": 1, + "speaker": "A" + }, + { + "text": "but", + "start": 194900, + "end": 195180, + "confidence": 0.953125, + "speaker": "A" + }, + { + "text": "what", + "start": 195340, + "end": 195620, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "do", + "start": 195620, + "end": 195780, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "you", + "start": 195780, + "end": 195940, + "confidence": 0.9946289, + "speaker": "A" + }, + { + "text": "think?", + "start": 195940, + "end": 196220, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "Well,", + "start": 198280, + "end": 198400, + "confidence": 0.9091797, + "speaker": "B" + }, + { + "text": "I", + "start": 198400, + "end": 198520, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "think", + "start": 198520, + "end": 198640, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 198640, + "end": 198760, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "fires", + "start": 198760, + "end": 199080, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "are", + "start": 199080, + "end": 199160, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "going", + "start": 199160, + "end": 199280, + "confidence": 0.67089844, + "speaker": "B" + }, + { + "text": "to", + "start": 199280, + "end": 199400, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "burn", + "start": 199400, + "end": 199560, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "for", + "start": 199560, + "end": 199680, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 199680, + "end": 199800, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "little", + "start": 199800, + "end": 199920, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "bit", + "start": 199920, + "end": 200080, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "longer.", + "start": 200080, + "end": 200440, + "confidence": 1, + "speaker": "B" + }, + { + "text": "But", + "start": 200440, + "end": 200640, + "confidence": 0.98876953, + "speaker": "B" + }, + { + "text": "the", + "start": 200640, + "end": 200840, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "key", + "start": 200840, + "end": 201120, + "confidence": 1, + "speaker": "B" + }, + { + "text": "for", + "start": 201120, + "end": 201400, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "us", + "start": 201400, + "end": 201640, + "confidence": 1, + "speaker": "B" + }, + { + "text": "in", + "start": 201640, + "end": 201800, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 201800, + "end": 201920, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "US", + "start": 201920, + "end": 202200, + "confidence": 0.98876953, + "speaker": "B" + }, + { + "text": "Is", + "start": 202200, + "end": 202480, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 202480, + "end": 202680, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "weather", + "start": 202680, + "end": 203000, + "confidence": 1, + "speaker": "B" + }, + { + "text": "system", + "start": 203000, + "end": 203280, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "changing.", + "start": 203280, + "end": 203800, + "confidence": 0.98828125, + "speaker": "B" + }, + { + "text": "Right", + "start": 203960, + "end": 204280, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "now", + "start": 204280, + "end": 204600, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "it's", + "start": 204680, + "end": 205080, + "confidence": 0.98258466, + "speaker": "B" + }, + { + "text": "the", + "start": 205080, + "end": 205280, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "weather", + "start": 205280, + "end": 205520, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "systems", + "start": 205520, + "end": 205840, + "confidence": 0.9987793, + "speaker": "B" + }, + { + "text": "that", + "start": 205840, + "end": 205960, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "are", + "start": 205960, + "end": 206080, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "pulling", + "start": 206080, + "end": 206320, + "confidence": 0.9996745, + "speaker": "B" + }, + { + "text": "that", + "start": 206320, + "end": 206480, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "air", + "start": 206480, + "end": 206760, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "into", + "start": 207320, + "end": 207640, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "our", + "start": 207640, + "end": 207960, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "Mid", + "start": 209080, + "end": 209400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "Atlantic", + "start": 209400, + "end": 209920, + "confidence": 0.88134766, + "speaker": "B" + }, + { + "text": "and", + "start": 209920, + "end": 210160, + "confidence": 0.87353516, + "speaker": "B" + }, + { + "text": "Northeast", + "start": 210160, + "end": 210720, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "region.", + "start": 210720, + "end": 211000, + "confidence": 1, + "speaker": "B" + }, + { + "text": "As", + "start": 211080, + "end": 211360, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "those", + "start": 211360, + "end": 211560, + "confidence": 0.9609375, + "speaker": "B" + }, + { + "text": "weather", + "start": 211560, + "end": 211960, + "confidence": 0.99194336, + "speaker": "B" + }, + { + "text": "systems", + "start": 212920, + "end": 213480, + "confidence": 0.99780273, + "speaker": "B" + }, + { + "text": "change", + "start": 213480, + "end": 213720, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 213720, + "end": 213960, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "shift,", + "start": 213960, + "end": 214360, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "we'll", + "start": 214520, + "end": 214840, + "confidence": 0.9785156, + "speaker": "B" + }, + { + "text": "see", + "start": 214840, + "end": 214960, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "that", + "start": 214960, + "end": 215120, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "smoke", + "start": 215120, + "end": 215400, + "confidence": 0.9900716, + "speaker": "B" + }, + { + "text": "going", + "start": 215400, + "end": 215640, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "elsewhere", + "start": 215640, + "end": 216120, + "confidence": 0.977417, + "speaker": "B" + }, + { + "text": "and", + "start": 216600, + "end": 216880, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "not", + "start": 216880, + "end": 217080, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "impact", + "start": 217080, + "end": 217400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "us", + "start": 217400, + "end": 217800, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "in", + "start": 217880, + "end": 218160, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "this", + "start": 218160, + "end": 218360, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "region", + "start": 218360, + "end": 218640, + "confidence": 1, + "speaker": "B" + }, + { + "text": "as", + "start": 218640, + "end": 218880, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "much.", + "start": 218880, + "end": 219160, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "I", + "start": 219320, + "end": 219560, + "confidence": 0.9736328, + "speaker": "B" + }, + { + "text": "think", + "start": 219560, + "end": 219680, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "that's", + "start": 219680, + "end": 219960, + "confidence": 0.9938151, + "speaker": "B" + }, + { + "text": "going", + "start": 219960, + "end": 220040, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "to", + "start": 220040, + "end": 220120, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "be", + "start": 220120, + "end": 220240, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 220240, + "end": 220400, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "defining", + "start": 220400, + "end": 220760, + "confidence": 1, + "speaker": "B" + }, + { + "text": "factor.", + "start": 220760, + "end": 221080, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "I", + "start": 221080, + "end": 221240, + "confidence": 0.97314453, + "speaker": "B" + }, + { + "text": "think", + "start": 221240, + "end": 221360, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 221360, + "end": 221480, + "confidence": 0.9902344, + "speaker": "B" + }, + { + "text": "next", + "start": 221480, + "end": 221600, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "couple", + "start": 221600, + "end": 221840, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "days", + "start": 221840, + "end": 222000, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "we're", + "start": 222000, + "end": 222200, + "confidence": 0.98844403, + "speaker": "B" + }, + { + "text": "going", + "start": 222200, + "end": 222320, + "confidence": 0.67578125, + "speaker": "B" + }, + { + "text": "to", + "start": 222320, + "end": 222600, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "see", + "start": 222600, + "end": 222880, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 222880, + "end": 223040, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "shift", + "start": 223040, + "end": 223400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "in", + "start": 224120, + "end": 224400, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "that", + "start": 224400, + "end": 224560, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "weather", + "start": 224560, + "end": 224800, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "pattern", + "start": 224800, + "end": 225120, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 225120, + "end": 225360, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "start", + "start": 225360, + "end": 225520, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "to", + "start": 225520, + "end": 225640, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "push", + "start": 225640, + "end": 225800, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 225800, + "end": 225920, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "smoke", + "start": 225920, + "end": 226160, + "confidence": 0.8540039, + "speaker": "B" + }, + { + "text": "away", + "start": 226160, + "end": 226400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "from", + "start": 226400, + "end": 226760, + "confidence": 0.6513672, + "speaker": "B" + }, + { + "text": "where", + "start": 226760, + "end": 227040, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "we", + "start": 227040, + "end": 227200, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "are.", + "start": 227200, + "end": 227480, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "And", + "start": 227930, + "end": 228050, + "confidence": 0.9433594, + "speaker": "A" + }, + { + "text": "finally,", + "start": 228050, + "end": 228410, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "with", + "start": 228410, + "end": 228650, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "the", + "start": 228650, + "end": 228930, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "impacts", + "start": 228930, + "end": 229370, + "confidence": 0.9921875, + "speaker": "A" + }, + { + "text": "of", + "start": 229370, + "end": 229530, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "climate", + "start": 229530, + "end": 229890, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "change,", + "start": 229890, + "end": 230210, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "we", + "start": 230210, + "end": 230450, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "are", + "start": 230450, + "end": 230650, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "seeing", + "start": 230650, + "end": 230970, + "confidence": 1, + "speaker": "A" + }, + { + "text": "more", + "start": 230970, + "end": 231290, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "wildfires.", + "start": 231290, + "end": 232250, + "confidence": 0.9993164, + "speaker": "A" + }, + { + "text": "Will", + "start": 232410, + "end": 232730, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "we", + "start": 232730, + "end": 232970, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "be", + "start": 232970, + "end": 233210, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "seeing", + "start": 233210, + "end": 233610, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "more", + "start": 233690, + "end": 234050, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 234050, + "end": 234290, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "these", + "start": 234290, + "end": 234530, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "kinds", + "start": 234530, + "end": 234890, + "confidence": 0.9914551, + "speaker": "A" + }, + { + "text": "of", + "start": 234890, + "end": 235130, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "wide", + "start": 235450, + "end": 235850, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "ranging", + "start": 235850, + "end": 236410, + "confidence": 0.9998372, + "speaker": "A" + }, + { + "text": "air", + "start": 237290, + "end": 237610, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "quality", + "start": 237610, + "end": 238050, + "confidence": 1, + "speaker": "A" + }, + { + "text": "consequences", + "start": 238050, + "end": 238690, + "confidence": 0.9385742, + "speaker": "A" + }, + { + "text": "or", + "start": 238690, + "end": 239050, + "confidence": 0.87841797, + "speaker": "A" + }, + { + "text": "circumstances?", + "start": 239130, + "end": 239850, + "confidence": 0.93204755, + "speaker": "A" + }, + { + "text": "I", + "start": 241370, + "end": 241650, + "confidence": 0.9238281, + "speaker": "B" + }, + { + "text": "mean,", + "start": 241650, + "end": 241810, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "that", + "start": 241810, + "end": 241930, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "is", + "start": 241930, + "end": 242090, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "one", + "start": 242090, + "end": 242250, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 242250, + "end": 242330, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 242330, + "end": 242450, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "predictions", + "start": 242450, + "end": 243050, + "confidence": 0.8977051, + "speaker": "B" + }, + { + "text": "for", + "start": 243050, + "end": 243450, + "confidence": 0.73095703, + "speaker": "B" + }, + { + "text": "climate", + "start": 244490, + "end": 244890, + "confidence": 1, + "speaker": "B" + }, + { + "text": "change.", + "start": 244890, + "end": 245130, + "confidence": 1, + "speaker": "B" + }, + { + "text": "Looking", + "start": 245130, + "end": 245370, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "into", + "start": 245370, + "end": 245570, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 245570, + "end": 245730, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "future,", + "start": 245730, + "end": 246010, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 246410, + "end": 246730, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "fire", + "start": 246730, + "end": 247010, + "confidence": 1, + "speaker": "B" + }, + { + "text": "season", + "start": 247010, + "end": 247290, + "confidence": 1, + "speaker": "B" + }, + { + "text": "is", + "start": 247290, + "end": 247490, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "starting", + "start": 247490, + "end": 247730, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "earlier", + "start": 247730, + "end": 247970, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "and", + "start": 247970, + "end": 248210, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "lasting", + "start": 248210, + "end": 248570, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "longer", + "start": 248570, + "end": 249050, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 249610, + "end": 249890, + "confidence": 0.9736328, + "speaker": "B" + }, + { + "text": "we're", + "start": 249890, + "end": 250090, + "confidence": 0.93815106, + "speaker": "B" + }, + { + "text": "seeing", + "start": 250090, + "end": 250290, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "more", + "start": 250290, + "end": 250450, + "confidence": 1, + "speaker": "B" + }, + { + "text": "frequent", + "start": 250450, + "end": 250810, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "fires.", + "start": 250810, + "end": 251290, + "confidence": 0.98950195, + "speaker": "B" + }, + { + "text": "So", + "start": 251290, + "end": 251610, + "confidence": 0.94628906, + "speaker": "B" + }, + { + "text": "yeah,", + "start": 252010, + "end": 252370, + "confidence": 0.9715169, + "speaker": "B" + }, + { + "text": "this", + "start": 252370, + "end": 252530, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "is", + "start": 252530, + "end": 252690, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "probably", + "start": 252690, + "end": 252970, + "confidence": 0.9973958, + "speaker": "B" + }, + { + "text": "something", + "start": 252970, + "end": 253290, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "that", + "start": 253290, + "end": 253690, + "confidence": 0.9863281, + "speaker": "B" + }, + { + "text": "we'll", + "start": 253770, + "end": 254090, + "confidence": 0.9835612, + "speaker": "B" + }, + { + "text": "be", + "start": 254090, + "end": 254210, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "seeing", + "start": 254210, + "end": 254530, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "more,", + "start": 254530, + "end": 254780, + "confidence": 0.5083008, + "speaker": "B" + }, + { + "text": "more", + "start": 254930, + "end": 255050, + "confidence": 0.8666992, + "speaker": "B" + }, + { + "text": "frequently.", + "start": 255050, + "end": 255570, + "confidence": 1, + "speaker": "B" + }, + { + "text": "This", + "start": 255650, + "end": 255930, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "tends", + "start": 255930, + "end": 256170, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "to", + "start": 256170, + "end": 256290, + "confidence": 1, + "speaker": "B" + }, + { + "text": "be", + "start": 256290, + "end": 256410, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "much", + "start": 256410, + "end": 256570, + "confidence": 0.9916992, + "speaker": "B" + }, + { + "text": "more", + "start": 256570, + "end": 256690, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 256690, + "end": 256770, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "an", + "start": 256770, + "end": 256890, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "issue", + "start": 256890, + "end": 257090, + "confidence": 1, + "speaker": "B" + }, + { + "text": "in", + "start": 257090, + "end": 257250, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 257250, + "end": 257330, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "western", + "start": 257330, + "end": 257610, + "confidence": 1, + "speaker": "B" + }, + { + "text": "U.S.", + "start": 257610, + "end": 257890, + "confidence": 0.99023, + "speaker": "B" + }, + { + "text": "so", + "start": 258130, + "end": 258410, + "confidence": 0.75439453, + "speaker": "B" + }, + { + "text": "the", + "start": 258410, + "end": 258530, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "eastern", + "start": 258530, + "end": 258770, + "confidence": 0.9916992, + "speaker": "B" + }, + { + "text": "U.S.", + "start": 258770, + "end": 259050, + "confidence": 0.99121, + "speaker": "B" + }, + { + "text": "getting", + "start": 259050, + "end": 259290, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hit", + "start": 259290, + "end": 259490, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "right", + "start": 259490, + "end": 259690, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "now", + "start": 259690, + "end": 259970, + "confidence": 1, + "speaker": "B" + }, + { + "text": "is", + "start": 260370, + "end": 260690, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "a", + "start": 260690, + "end": 260850, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "little", + "start": 260850, + "end": 260970, + "confidence": 1, + "speaker": "B" + }, + { + "text": "bit", + "start": 260970, + "end": 261170, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "new.", + "start": 261170, + "end": 261490, + "confidence": 1, + "speaker": "B" + }, + { + "text": "But", + "start": 262210, + "end": 262530, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "yeah,", + "start": 262530, + "end": 262850, + "confidence": 0.97314453, + "speaker": "B" + }, + { + "text": "I", + "start": 262850, + "end": 263010, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "think", + "start": 263010, + "end": 263130, + "confidence": 1, + "speaker": "B" + }, + { + "text": "with", + "start": 263130, + "end": 263330, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "climate", + "start": 263330, + "end": 263650, + "confidence": 1, + "speaker": "B" + }, + { + "text": "change", + "start": 263650, + "end": 263930, + "confidence": 1, + "speaker": "B" + }, + { + "text": "moving", + "start": 263930, + "end": 264330, + "confidence": 1, + "speaker": "B" + }, + { + "text": "forward,", + "start": 264330, + "end": 264690, + "confidence": 1, + "speaker": "B" + }, + { + "text": "this", + "start": 264690, + "end": 264970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "is", + "start": 264970, + "end": 265130, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "something", + "start": 265130, + "end": 265330, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "that", + "start": 265330, + "end": 265650, + "confidence": 0.9951172, + "speaker": "B" + }, + { + "text": "is", + "start": 266130, + "end": 266410, + "confidence": 0.97558594, + "speaker": "B" + }, + { + "text": "going", + "start": 266410, + "end": 266530, + "confidence": 0.66503906, + "speaker": "B" + }, + { + "text": "to", + "start": 266530, + "end": 266610, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "happen", + "start": 266610, + "end": 266770, + "confidence": 1, + "speaker": "B" + }, + { + "text": "more", + "start": 266770, + "end": 266970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "frequently.", + "start": 266970, + "end": 267570, + "confidence": 0.959668, + "speaker": "B" + }, + { + "text": "That's", + "start": 267970, + "end": 268290, + "confidence": 0.9977214, + "speaker": "A" + }, + { + "text": "Peter", + "start": 268290, + "end": 268610, + "confidence": 0.99780273, + "speaker": "A" + }, + { + "text": "DeCarlo,", + "start": 268610, + "end": 269290, + "confidence": 0.94775, + "speaker": "A" + }, + { + "text": "associate", + "start": 269290, + "end": 269730, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "professor", + "start": 269730, + "end": 270170, + "confidence": 1, + "speaker": "A" + }, + { + "text": "in", + "start": 270170, + "end": 270290, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "the", + "start": 270290, + "end": 270410, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Department", + "start": 270410, + "end": 270690, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 270770, + "end": 271009, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Environmental", + "start": 271009, + "end": 271610, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "Health", + "start": 271610, + "end": 271850, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "and", + "start": 271850, + "end": 272090, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "Engineering", + "start": 272090, + "end": 272610, + "confidence": 1, + "speaker": "A" + }, + { + "text": "at", + "start": 272770, + "end": 273090, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Johns", + "start": 273090, + "end": 273530, + "confidence": 0.9777832, + "speaker": "A" + }, + { + "text": "Hopkins", + "start": 273530, + "end": 274050, + "confidence": 1, + "speaker": "A" + }, + { + "text": "University.", + "start": 274130, + "end": 274530, + "confidence": 1, + "speaker": "A" + }, + { + "text": "Professor", + "start": 274610, + "end": 275130, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "DeCarlo,", + "start": 275130, + "end": 275650, + "confidence": 0.96191, + "speaker": "A" + }, + { + "text": "thanks", + "start": 275650, + "end": 275890, + "confidence": 0.9951172, + "speaker": "A" + }, + { + "text": "so", + "start": 275890, + "end": 275970, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "much", + "start": 275970, + "end": 276090, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "for", + "start": 276090, + "end": 276250, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "joining", + "start": 276250, + "end": 276490, + "confidence": 0.90201825, + "speaker": "A" + }, + { + "text": "us", + "start": 276490, + "end": 276650, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "and", + "start": 276650, + "end": 276810, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "sharing", + "start": 276810, + "end": 277050, + "confidence": 0.99731445, + "speaker": "A" + }, + { + "text": "this", + "start": 277050, + "end": 277250, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "expertise", + "start": 277250, + "end": 277730, + "confidence": 0.89729816, + "speaker": "A" + }, + { + "text": "with", + "start": 277730, + "end": 277930, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "us.", + "start": 277930, + "end": 278210, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Thank", + "start": 279410, + "end": 279770, + "confidence": 0.99365234, + "speaker": "B" + }, + { + "text": "you", + "start": 279770, + "end": 279930, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "for", + "start": 279930, + "end": 280050, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "having", + "start": 280050, + "end": 280210, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "me.", + "start": 280210, + "end": 280530, + "confidence": 0.9980469, + "speaker": "B" + } + ], + "utterances": [ + { + "speaker": "A", + "text": "Smoke from hundreds of wildfires in Canada is triggering air quality alerts throughout the US Skylines from Maine to Maryland to Minnesota are gray and smoggy. And in some places, the air quality warnings include the warning to stay inside. We wanted to better understand what's happening here and why, so we called Peter DeCarlo, an associate professor in the Department of Environmental Health and Engineering at Johns Hopkins University. Good morning, Professor.", + "confidence": 0.9815734, + "start": 240, + "end": 26560, + "words": [ + { + "text": "Smoke", + "start": 240, + "end": 640, + "confidence": 0.90152997, + "speaker": "A" + }, + { + "text": "from", + "start": 640, + "end": 1000, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "hundreds", + "start": 1000, + "end": 1480, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "of", + "start": 1480, + "end": 1640, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "wildfires", + "start": 1640, + "end": 2320, + "confidence": 0.99970704, + "speaker": "A" + }, + { + "text": "in", + "start": 2320, + "end": 2480, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "Canada", + "start": 2480, + "end": 2800, + "confidence": 1, + "speaker": "A" + }, + { + "text": "is", + "start": 3120, + "end": 3440, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "triggering", + "start": 3440, + "end": 3920, + "confidence": 0.9998779, + "speaker": "A" + }, + { + "text": "air", + "start": 3920, + "end": 4160, + "confidence": 1, + "speaker": "A" + }, + { + "text": "quality", + "start": 4160, + "end": 4640, + "confidence": 0.78100586, + "speaker": "A" + }, + { + "text": "alerts", + "start": 4640, + "end": 5120, + "confidence": 0.9013672, + "speaker": "A" + }, + { + "text": "throughout", + "start": 5120, + "end": 5480, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "the", + "start": 5480, + "end": 5680, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "US", + "start": 5680, + "end": 6000, + "confidence": 0.9770508, + "speaker": "A" + }, + { + "text": "Skylines", + "start": 6480, + "end": 7280, + "confidence": 0.9996338, + "speaker": "A" + }, + { + "text": "from", + "start": 7280, + "end": 7440, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "Maine", + "start": 7440, + "end": 7920, + "confidence": 0.84106445, + "speaker": "A" + }, + { + "text": "to", + "start": 8000, + "end": 8280, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "Maryland", + "start": 8280, + "end": 8680, + "confidence": 0.9978841, + "speaker": "A" + }, + { + "text": "to", + "start": 8680, + "end": 8920, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "Minnesota", + "start": 8920, + "end": 9640, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "are", + "start": 9640, + "end": 9920, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "gray", + "start": 9920, + "end": 10200, + "confidence": 0.7348633, + "speaker": "A" + }, + { + "text": "and", + "start": 10200, + "end": 10400, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "smoggy.", + "start": 10400, + "end": 11040, + "confidence": 0.9984131, + "speaker": "A" + }, + { + "text": "And", + "start": 11040, + "end": 11360, + "confidence": 0.97021484, + "speaker": "A" + }, + { + "text": "in", + "start": 11360, + "end": 11560, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "some", + "start": 11560, + "end": 11760, + "confidence": 1, + "speaker": "A" + }, + { + "text": "places,", + "start": 11760, + "end": 12120, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "the", + "start": 12120, + "end": 12320, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "air", + "start": 12320, + "end": 12560, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "quality", + "start": 12560, + "end": 12960, + "confidence": 1, + "speaker": "A" + }, + { + "text": "warnings", + "start": 12960, + "end": 13400, + "confidence": 0.99820966, + "speaker": "A" + }, + { + "text": "include", + "start": 13400, + "end": 13680, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "the", + "start": 13680, + "end": 13960, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "warning", + "start": 13960, + "end": 14240, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "to", + "start": 14240, + "end": 14480, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "stay", + "start": 14480, + "end": 14800, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "inside.", + "start": 14880, + "end": 15520, + "confidence": 1, + "speaker": "A" + }, + { + "text": "We", + "start": 15919, + "end": 16199, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "wanted", + "start": 16199, + "end": 16400, + "confidence": 0.99243164, + "speaker": "A" + }, + { + "text": "to", + "start": 16400, + "end": 16520, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "better", + "start": 16520, + "end": 16720, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "understand", + "start": 16720, + "end": 17040, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "what's", + "start": 17040, + "end": 17440, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "happening", + "start": 17440, + "end": 17760, + "confidence": 0.8527832, + "speaker": "A" + }, + { + "text": "here", + "start": 17760, + "end": 18000, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "and", + "start": 18000, + "end": 18200, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "why,", + "start": 18200, + "end": 18440, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "so", + "start": 18440, + "end": 18640, + "confidence": 0.9863281, + "speaker": "A" + }, + { + "text": "we", + "start": 18640, + "end": 18760, + "confidence": 0.9838867, + "speaker": "A" + }, + { + "text": "called", + "start": 18760, + "end": 18920, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "Peter", + "start": 18920, + "end": 19240, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "DeCarlo,", + "start": 19240, + "end": 19920, + "confidence": 0.88265, + "speaker": "A" + }, + { + "text": "an", + "start": 20000, + "end": 20280, + "confidence": 0.9604492, + "speaker": "A" + }, + { + "text": "associate", + "start": 20280, + "end": 20720, + "confidence": 1, + "speaker": "A" + }, + { + "text": "professor", + "start": 20720, + "end": 21160, + "confidence": 1, + "speaker": "A" + }, + { + "text": "in", + "start": 21160, + "end": 21320, + "confidence": 0.99316406, + "speaker": "A" + }, + { + "text": "the", + "start": 21320, + "end": 21480, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "Department", + "start": 21480, + "end": 21760, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "of", + "start": 21760, + "end": 22040, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Environmental", + "start": 22040, + "end": 22720, + "confidence": 0.9987793, + "speaker": "A" + }, + { + "text": "Health", + "start": 22720, + "end": 22960, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "and", + "start": 22960, + "end": 23200, + "confidence": 0.9951172, + "speaker": "A" + }, + { + "text": "Engineering", + "start": 23200, + "end": 23680, + "confidence": 1, + "speaker": "A" + }, + { + "text": "at", + "start": 23680, + "end": 23920, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "Johns", + "start": 23920, + "end": 24360, + "confidence": 0.9733887, + "speaker": "A" + }, + { + "text": "Hopkins", + "start": 24360, + "end": 24840, + "confidence": 1, + "speaker": "A" + }, + { + "text": "University.", + "start": 24840, + "end": 25200, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Good", + "start": 25520, + "end": 25800, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "morning,", + "start": 25800, + "end": 26000, + "confidence": 1, + "speaker": "A" + }, + { + "text": "Professor.", + "start": 26000, + "end": 26560, + "confidence": 0.9995117, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "Good morning.", + "confidence": 0.98217773, + "start": 28060, + "end": 28620, + "words": [ + { + "text": "Good", + "start": 28060, + "end": 28260, + "confidence": 0.96484375, + "speaker": "B" + }, + { + "text": "morning.", + "start": 28260, + "end": 28620, + "confidence": 0.9995117, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "So what is it about the conditions right now that have caused this round of wildfires to affect so many people so far away?", + "confidence": 0.9814351, + "start": 29100, + "end": 37100, + "words": [ + { + "text": "So", + "start": 29100, + "end": 29500, + "confidence": 0.6220703, + "speaker": "A" + }, + { + "text": "what", + "start": 29660, + "end": 29940, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "is", + "start": 29940, + "end": 30100, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "it", + "start": 30100, + "end": 30260, + "confidence": 0.9941406, + "speaker": "A" + }, + { + "text": "about", + "start": 30260, + "end": 30500, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "the", + "start": 30500, + "end": 30740, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "conditions", + "start": 30740, + "end": 31260, + "confidence": 1, + "speaker": "A" + }, + { + "text": "right", + "start": 31260, + "end": 31660, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "now", + "start": 31660, + "end": 32060, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "that", + "start": 32140, + "end": 32420, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "have", + "start": 32420, + "end": 32620, + "confidence": 0.99121094, + "speaker": "A" + }, + { + "text": "caused", + "start": 32620, + "end": 32980, + "confidence": 0.9707031, + "speaker": "A" + }, + { + "text": "this", + "start": 32980, + "end": 33260, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "round", + "start": 33260, + "end": 33500, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 33500, + "end": 33740, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "wildfires", + "start": 33740, + "end": 34540, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "to", + "start": 34540, + "end": 34700, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "affect", + "start": 34700, + "end": 35140, + "confidence": 0.9914551, + "speaker": "A" + }, + { + "text": "so", + "start": 35140, + "end": 35380, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "many", + "start": 35380, + "end": 35580, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "people", + "start": 35580, + "end": 35900, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "so", + "start": 36300, + "end": 36580, + "confidence": 1, + "speaker": "A" + }, + { + "text": "far", + "start": 36580, + "end": 36780, + "confidence": 1, + "speaker": "A" + }, + { + "text": "away?", + "start": 36780, + "end": 37100, + "confidence": 0.9975586, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "Well, there's a couple of things. The season has been pretty dry already, and then the fact that we're getting hit in the US is because there's a couple weather systems that are essentially channeling the smoke from those Canadian wildfires through Pennsylvania into the mid Atlantic and the Northeast and kind of just dropping the smoke there.", + "confidence": 0.97739446, + "start": 39100, + "end": 55820, + "words": [ + { + "text": "Well,", + "start": 39100, + "end": 39380, + "confidence": 0.9394531, + "speaker": "B" + }, + { + "text": "there's", + "start": 39380, + "end": 39580, + "confidence": 0.98844403, + "speaker": "B" + }, + { + "text": "a", + "start": 39580, + "end": 39660, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "couple", + "start": 39660, + "end": 39860, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "of", + "start": 39860, + "end": 40020, + "confidence": 0.94628906, + "speaker": "B" + }, + { + "text": "things.", + "start": 40020, + "end": 40300, + "confidence": 0.9428711, + "speaker": "B" + }, + { + "text": "The", + "start": 41020, + "end": 41340, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "season", + "start": 41340, + "end": 41620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "has", + "start": 41620, + "end": 41820, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "been", + "start": 41820, + "end": 41940, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "pretty", + "start": 41940, + "end": 42140, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "dry", + "start": 42140, + "end": 42340, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "already,", + "start": 42340, + "end": 42620, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "and", + "start": 43020, + "end": 43340, + "confidence": 0.9794922, + "speaker": "B" + }, + { + "text": "then", + "start": 43340, + "end": 43660, + "confidence": 0.9892578, + "speaker": "B" + }, + { + "text": "the", + "start": 43660, + "end": 43940, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "fact", + "start": 43940, + "end": 44100, + "confidence": 1, + "speaker": "B" + }, + { + "text": "that", + "start": 44100, + "end": 44260, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "we're", + "start": 44260, + "end": 44500, + "confidence": 0.8828125, + "speaker": "B" + }, + { + "text": "getting", + "start": 44500, + "end": 44740, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hit", + "start": 44740, + "end": 44980, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "in", + "start": 44980, + "end": 45140, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 45140, + "end": 45300, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "US", + "start": 45300, + "end": 45580, + "confidence": 0.9863281, + "speaker": "B" + }, + { + "text": "is", + "start": 46140, + "end": 46460, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "because", + "start": 46460, + "end": 46700, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "there's", + "start": 46700, + "end": 47020, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "a", + "start": 47020, + "end": 47100, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "couple", + "start": 47100, + "end": 47340, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "weather", + "start": 47340, + "end": 47660, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "systems", + "start": 47660, + "end": 47980, + "confidence": 0.9987793, + "speaker": "B" + }, + { + "text": "that", + "start": 47980, + "end": 48060, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "are", + "start": 48060, + "end": 48180, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "essentially", + "start": 48180, + "end": 48580, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "channeling", + "start": 48580, + "end": 49020, + "confidence": 0.970459, + "speaker": "B" + }, + { + "text": "the", + "start": 49020, + "end": 49140, + "confidence": 0.98828125, + "speaker": "B" + }, + { + "text": "smoke", + "start": 49140, + "end": 49380, + "confidence": 0.9682617, + "speaker": "B" + }, + { + "text": "from", + "start": 49380, + "end": 49540, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "those", + "start": 49540, + "end": 49700, + "confidence": 0.96875, + "speaker": "B" + }, + { + "text": "Canadian", + "start": 49700, + "end": 50100, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "wildfires", + "start": 50100, + "end": 50780, + "confidence": 0.9993164, + "speaker": "B" + }, + { + "text": "through", + "start": 51260, + "end": 51620, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "Pennsylvania", + "start": 51620, + "end": 52340, + "confidence": 0.9989692, + "speaker": "B" + }, + { + "text": "into", + "start": 52340, + "end": 52500, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 52500, + "end": 52660, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "mid", + "start": 52660, + "end": 52820, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "Atlantic", + "start": 52820, + "end": 53180, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "and", + "start": 53180, + "end": 53300, + "confidence": 0.52978516, + "speaker": "B" + }, + { + "text": "the", + "start": 53300, + "end": 53420, + "confidence": 0.9785156, + "speaker": "B" + }, + { + "text": "Northeast", + "start": 53420, + "end": 53860, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "and", + "start": 53860, + "end": 54140, + "confidence": 0.8803711, + "speaker": "B" + }, + { + "text": "kind", + "start": 54220, + "end": 54460, + "confidence": 0.8515625, + "speaker": "B" + }, + { + "text": "of", + "start": 54460, + "end": 54580, + "confidence": 0.98779297, + "speaker": "B" + }, + { + "text": "just", + "start": 54580, + "end": 54740, + "confidence": 0.98583984, + "speaker": "B" + }, + { + "text": "dropping", + "start": 54740, + "end": 55140, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "the", + "start": 55140, + "end": 55260, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "smoke", + "start": 55260, + "end": 55540, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "there.", + "start": 55540, + "end": 55820, + "confidence": 0.9975586, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "So what is it in this haze that makes it harmful? And I'm assuming it is harmful.", + "confidence": 0.9638959, + "start": 56590, + "end": 60670, + "words": [ + { + "text": "So", + "start": 56590, + "end": 56670, + "confidence": 0.8666992, + "speaker": "A" + }, + { + "text": "what", + "start": 56670, + "end": 56790, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "is", + "start": 56790, + "end": 56950, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "it", + "start": 56950, + "end": 57110, + "confidence": 0.9814453, + "speaker": "A" + }, + { + "text": "in", + "start": 57110, + "end": 57270, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "this", + "start": 57270, + "end": 57470, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "haze", + "start": 57470, + "end": 57910, + "confidence": 0.9347331, + "speaker": "A" + }, + { + "text": "that", + "start": 57910, + "end": 58110, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "makes", + "start": 58110, + "end": 58430, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "it", + "start": 58510, + "end": 58830, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "harmful?", + "start": 58830, + "end": 59310, + "confidence": 0.9998372, + "speaker": "A" + }, + { + "text": "And", + "start": 59310, + "end": 59470, + "confidence": 0.71435547, + "speaker": "A" + }, + { + "text": "I'm", + "start": 59470, + "end": 59670, + "confidence": 0.98307294, + "speaker": "A" + }, + { + "text": "assuming", + "start": 59670, + "end": 59990, + "confidence": 1, + "speaker": "A" + }, + { + "text": "it", + "start": 59990, + "end": 60110, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "is", + "start": 60110, + "end": 60230, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "harmful.", + "start": 60230, + "end": 60670, + "confidence": 0.91780597, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "It is, it is. The levels outside right now in Baltimore are considered unhealthy. And most of that is due to what's called particulate matter, which are tiny particles, microscopic, smaller than the width of your hair, that can get into your lungs and impact your respiratory system, your cardiovascular system, and even your neurological, your brain.", + "confidence": 0.9743181, + "start": 62350, + "end": 82590, + "words": [ + { + "text": "It", + "start": 62350, + "end": 62630, + "confidence": 0.9238281, + "speaker": "B" + }, + { + "text": "is,", + "start": 62630, + "end": 62870, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "it", + "start": 62870, + "end": 63110, + "confidence": 0.8666992, + "speaker": "B" + }, + { + "text": "is.", + "start": 63110, + "end": 63350, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "The", + "start": 63350, + "end": 63590, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "levels", + "start": 63590, + "end": 64030, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "outside", + "start": 64030, + "end": 64430, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "right", + "start": 64510, + "end": 64790, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "now", + "start": 64790, + "end": 64950, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "in", + "start": 64950, + "end": 65110, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "Baltimore", + "start": 65110, + "end": 65590, + "confidence": 0.9998047, + "speaker": "B" + }, + { + "text": "are", + "start": 65590, + "end": 65750, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "considered", + "start": 65750, + "end": 66070, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "unhealthy.", + "start": 66070, + "end": 66750, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "And", + "start": 67790, + "end": 68110, + "confidence": 0.67822266, + "speaker": "B" + }, + { + "text": "most", + "start": 68110, + "end": 68310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 68310, + "end": 68470, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "that", + "start": 68470, + "end": 68630, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "is", + "start": 68630, + "end": 68790, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "due", + "start": 68790, + "end": 68990, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "to", + "start": 68990, + "end": 69270, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "what's", + "start": 69270, + "end": 69630, + "confidence": 0.9916992, + "speaker": "B" + }, + { + "text": "called", + "start": 69630, + "end": 69750, + "confidence": 1, + "speaker": "B" + }, + { + "text": "particulate", + "start": 69750, + "end": 70310, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "matter,", + "start": 70310, + "end": 70470, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "which", + "start": 70470, + "end": 70670, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "are", + "start": 70670, + "end": 70870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "tiny", + "start": 70870, + "end": 71190, + "confidence": 1, + "speaker": "B" + }, + { + "text": "particles,", + "start": 71190, + "end": 71630, + "confidence": 0.7578125, + "speaker": "B" + }, + { + "text": "microscopic,", + "start": 72110, + "end": 72910, + "confidence": 0.97957355, + "speaker": "B" + }, + { + "text": "smaller", + "start": 72910, + "end": 73310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "than", + "start": 73310, + "end": 73390, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 73390, + "end": 73470, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "width", + "start": 73470, + "end": 73670, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 73670, + "end": 73950, + "confidence": 0.98095703, + "speaker": "B" + }, + { + "text": "your", + "start": 73950, + "end": 74270, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hair,", + "start": 74270, + "end": 74670, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "that", + "start": 75230, + "end": 75550, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "can", + "start": 75550, + "end": 75750, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "get", + "start": 75750, + "end": 75910, + "confidence": 1, + "speaker": "B" + }, + { + "text": "into", + "start": 75910, + "end": 76070, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "your", + "start": 76070, + "end": 76230, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "lungs", + "start": 76230, + "end": 76550, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 76550, + "end": 76830, + "confidence": 0.9145508, + "speaker": "B" + }, + { + "text": "impact", + "start": 76910, + "end": 77270, + "confidence": 1, + "speaker": "B" + }, + { + "text": "your", + "start": 77270, + "end": 77590, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "respiratory", + "start": 77590, + "end": 78150, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "system,", + "start": 78150, + "end": 78470, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "your", + "start": 78470, + "end": 78710, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "cardiovascular", + "start": 78710, + "end": 79470, + "confidence": 0.99958146, + "speaker": "B" + }, + { + "text": "system,", + "start": 79470, + "end": 79790, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 80430, + "end": 80710, + "confidence": 0.99121094, + "speaker": "B" + }, + { + "text": "even", + "start": 80710, + "end": 80910, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "your", + "start": 80910, + "end": 81230, + "confidence": 0.53027344, + "speaker": "B" + }, + { + "text": "neurological,", + "start": 81310, + "end": 82030, + "confidence": 0.99768066, + "speaker": "B" + }, + { + "text": "your", + "start": 82030, + "end": 82230, + "confidence": 0.9746094, + "speaker": "B" + }, + { + "text": "brain.", + "start": 82230, + "end": 82590, + "confidence": 0.9992676, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "What makes this particularly harmful? Is it the volume of particulate? Is it something in particular? What is it exactly? Can you just drill down on that a little bit more?", + "confidence": 0.9699182, + "start": 83630, + "end": 92190, + "words": [ + { + "text": "What", + "start": 83630, + "end": 83790, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "makes", + "start": 83790, + "end": 83990, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "this", + "start": 83990, + "end": 84190, + "confidence": 0.9423828, + "speaker": "A" + }, + { + "text": "particularly", + "start": 84190, + "end": 84990, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "harmful?", + "start": 84990, + "end": 85550, + "confidence": 0.9998372, + "speaker": "A" + }, + { + "text": "Is", + "start": 85550, + "end": 85750, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "it", + "start": 85750, + "end": 85870, + "confidence": 0.9946289, + "speaker": "A" + }, + { + "text": "the", + "start": 85870, + "end": 86110, + "confidence": 0.59228516, + "speaker": "A" + }, + { + "text": "volume", + "start": 86670, + "end": 87150, + "confidence": 0.8741862, + "speaker": "A" + }, + { + "text": "of", + "start": 87150, + "end": 87390, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "particulate?", + "start": 87390, + "end": 88030, + "confidence": 0.8585612, + "speaker": "A" + }, + { + "text": "Is", + "start": 88030, + "end": 88230, + "confidence": 0.9892578, + "speaker": "A" + }, + { + "text": "it", + "start": 88230, + "end": 88390, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "something", + "start": 88390, + "end": 88590, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "in", + "start": 88590, + "end": 88790, + "confidence": 0.96435547, + "speaker": "A" + }, + { + "text": "particular?", + "start": 88790, + "end": 89070, + "confidence": 0.97753906, + "speaker": "A" + }, + { + "text": "What", + "start": 89390, + "end": 89670, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "is", + "start": 89670, + "end": 89790, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "it", + "start": 89790, + "end": 89910, + "confidence": 0.9946289, + "speaker": "A" + }, + { + "text": "exactly?", + "start": 89910, + "end": 90350, + "confidence": 0.92545575, + "speaker": "A" + }, + { + "text": "Can", + "start": 90350, + "end": 90510, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "you", + "start": 90510, + "end": 90590, + "confidence": 1, + "speaker": "A" + }, + { + "text": "just", + "start": 90590, + "end": 90790, + "confidence": 0.98095703, + "speaker": "A" + }, + { + "text": "drill", + "start": 90790, + "end": 91070, + "confidence": 1, + "speaker": "A" + }, + { + "text": "down", + "start": 91070, + "end": 91190, + "confidence": 1, + "speaker": "A" + }, + { + "text": "on", + "start": 91190, + "end": 91350, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "that", + "start": 91350, + "end": 91510, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "a", + "start": 91510, + "end": 91630, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "little", + "start": 91630, + "end": 91750, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "bit", + "start": 91750, + "end": 91910, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "more?", + "start": 91910, + "end": 92190, + "confidence": 0.99902344, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "Yeah. So the concentration of particulate matter, I was looking at some of the monitors that we have was reaching levels of what are, in science speak, 150 micrograms per meter cubed, which is more than 10 times what the annual average should be in about four times higher than what you're supposed to have on a 24 hour average. And so the concentrations of these particles in the air are just much, much, much higher than we typically see. And exposure to those high levels can lead to a host of health problems.", + "confidence": 0.9856108, + "start": 93550, + "end": 123350, + "words": [ + { + "text": "Yeah.", + "start": 93550, + "end": 93950, + "confidence": 0.9145508, + "speaker": "B" + }, + { + "text": "So", + "start": 93950, + "end": 94150, + "confidence": 0.5620117, + "speaker": "B" + }, + { + "text": "the", + "start": 94150, + "end": 94310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "concentration", + "start": 94310, + "end": 94830, + "confidence": 1, + "speaker": "B" + }, + { + "text": "of", + "start": 94830, + "end": 95070, + "confidence": 1, + "speaker": "B" + }, + { + "text": "particulate", + "start": 95070, + "end": 95630, + "confidence": 0.99934894, + "speaker": "B" + }, + { + "text": "matter,", + "start": 95630, + "end": 95950, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "I", + "start": 96350, + "end": 96590, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "was", + "start": 96590, + "end": 96710, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "looking", + "start": 96710, + "end": 96870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "at", + "start": 96870, + "end": 96990, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "some", + "start": 96990, + "end": 97110, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "of", + "start": 97110, + "end": 97230, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 97230, + "end": 97310, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "monitors", + "start": 97310, + "end": 97630, + "confidence": 0.99934894, + "speaker": "B" + }, + { + "text": "that", + "start": 97630, + "end": 97750, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "we", + "start": 97750, + "end": 97910, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "have", + "start": 97910, + "end": 98190, + "confidence": 0.94677734, + "speaker": "B" + }, + { + "text": "was", + "start": 98270, + "end": 98550, + "confidence": 0.9838867, + "speaker": "B" + }, + { + "text": "reaching", + "start": 98550, + "end": 98869, + "confidence": 1, + "speaker": "B" + }, + { + "text": "levels", + "start": 98869, + "end": 99150, + "confidence": 1, + "speaker": "B" + }, + { + "text": "of", + "start": 99150, + "end": 99270, + "confidence": 0.9921875, + "speaker": "B" + }, + { + "text": "what", + "start": 99270, + "end": 99430, + "confidence": 0.88671875, + "speaker": "B" + }, + { + "text": "are,", + "start": 99430, + "end": 99710, + "confidence": 0.97509766, + "speaker": "B" + }, + { + "text": "in", + "start": 100910, + "end": 101190, + "confidence": 0.9838867, + "speaker": "B" + }, + { + "text": "science", + "start": 101190, + "end": 101430, + "confidence": 0.99731445, + "speaker": "B" + }, + { + "text": "speak,", + "start": 101430, + "end": 101710, + "confidence": 0.8635254, + "speaker": "B" + }, + { + "text": "150", + "start": 101710, + "end": 102350, + "confidence": 0.98551, + "speaker": "B" + }, + { + "text": "micrograms", + "start": 102350, + "end": 102910, + "confidence": 0.9963379, + "speaker": "B" + }, + { + "text": "per", + "start": 102910, + "end": 103030, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "meter", + "start": 103030, + "end": 103350, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "cubed,", + "start": 103350, + "end": 103670, + "confidence": 0.9954427, + "speaker": "B" + }, + { + "text": "which", + "start": 103670, + "end": 103830, + "confidence": 1, + "speaker": "B" + }, + { + "text": "is", + "start": 103830, + "end": 104110, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "more", + "start": 104270, + "end": 104550, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 104550, + "end": 104790, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "10", + "start": 104790, + "end": 105110, + "confidence": 1, + "speaker": "B" + }, + { + "text": "times", + "start": 105110, + "end": 105390, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "what", + "start": 105390, + "end": 105590, + "confidence": 0.99365234, + "speaker": "B" + }, + { + "text": "the", + "start": 105590, + "end": 105750, + "confidence": 1, + "speaker": "B" + }, + { + "text": "annual", + "start": 105750, + "end": 106110, + "confidence": 1, + "speaker": "B" + }, + { + "text": "average", + "start": 106110, + "end": 106510, + "confidence": 1, + "speaker": "B" + }, + { + "text": "should", + "start": 106510, + "end": 106790, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "be", + "start": 106790, + "end": 107150, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "in", + "start": 107390, + "end": 107670, + "confidence": 0.87841797, + "speaker": "B" + }, + { + "text": "about", + "start": 107670, + "end": 107950, + "confidence": 0.9711914, + "speaker": "B" + }, + { + "text": "four", + "start": 109110, + "end": 109270, + "confidence": 0.98046875, + "speaker": "B" + }, + { + "text": "times", + "start": 109270, + "end": 109550, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "higher", + "start": 109550, + "end": 109790, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 109790, + "end": 109950, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "what", + "start": 109950, + "end": 110070, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "you're", + "start": 110070, + "end": 110270, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "supposed", + "start": 110270, + "end": 110510, + "confidence": 0.998291, + "speaker": "B" + }, + { + "text": "to", + "start": 110510, + "end": 110670, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "have", + "start": 110670, + "end": 110950, + "confidence": 1, + "speaker": "B" + }, + { + "text": "on", + "start": 111350, + "end": 111670, + "confidence": 1, + "speaker": "B" + }, + { + "text": "a", + "start": 111670, + "end": 111910, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "24", + "start": 111910, + "end": 112390, + "confidence": 1, + "speaker": "B" + }, + { + "text": "hour", + "start": 112390, + "end": 112630, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "average.", + "start": 112630, + "end": 113110, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "And", + "start": 113350, + "end": 113710, + "confidence": 0.8989258, + "speaker": "B" + }, + { + "text": "so", + "start": 113710, + "end": 114070, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 114070, + "end": 114390, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "concentrations", + "start": 114390, + "end": 115110, + "confidence": 0.99816895, + "speaker": "B" + }, + { + "text": "of", + "start": 115110, + "end": 115230, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "these", + "start": 115230, + "end": 115390, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "particles", + "start": 115390, + "end": 115710, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "in", + "start": 115710, + "end": 115830, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 115830, + "end": 115950, + "confidence": 0.98583984, + "speaker": "B" + }, + { + "text": "air", + "start": 115950, + "end": 116230, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "are", + "start": 116550, + "end": 116870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "just", + "start": 116870, + "end": 117190, + "confidence": 0.9838867, + "speaker": "B" + }, + { + "text": "much,", + "start": 117350, + "end": 117710, + "confidence": 0.9873047, + "speaker": "B" + }, + { + "text": "much,", + "start": 117710, + "end": 117950, + "confidence": 1, + "speaker": "B" + }, + { + "text": "much", + "start": 117950, + "end": 118150, + "confidence": 1, + "speaker": "B" + }, + { + "text": "higher", + "start": 118150, + "end": 118350, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 118350, + "end": 118630, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "we", + "start": 118630, + "end": 118910, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "typically", + "start": 118910, + "end": 119270, + "confidence": 1, + "speaker": "B" + }, + { + "text": "see.", + "start": 119270, + "end": 119590, + "confidence": 1, + "speaker": "B" + }, + { + "text": "And", + "start": 119750, + "end": 120110, + "confidence": 0.98291016, + "speaker": "B" + }, + { + "text": "exposure", + "start": 120110, + "end": 120710, + "confidence": 0.9996745, + "speaker": "B" + }, + { + "text": "to", + "start": 120710, + "end": 120910, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "those", + "start": 120910, + "end": 121110, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "high", + "start": 121110, + "end": 121350, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "levels", + "start": 121350, + "end": 121710, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "can", + "start": 121710, + "end": 121870, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "lead", + "start": 121870, + "end": 122030, + "confidence": 1, + "speaker": "B" + }, + { + "text": "to", + "start": 122030, + "end": 122150, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 122150, + "end": 122270, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "host", + "start": 122270, + "end": 122430, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 122430, + "end": 122630, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "health", + "start": 122630, + "end": 122870, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "problems.", + "start": 122870, + "end": 123350, + "confidence": 0.9995117, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "And who is most vulnerable? I noticed that in New York City, for example, they're canceling outdoor activities. And so here it is in the early days of summer and they have to keep all the kids inside. So who tends to be vulnerable in a situation like this?", + "confidence": 0.9823397, + "start": 123430, + "end": 135990, + "words": [ + { + "text": "And", + "start": 123430, + "end": 123710, + "confidence": 0.94970703, + "speaker": "A" + }, + { + "text": "who", + "start": 123710, + "end": 123870, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "is", + "start": 123870, + "end": 124070, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "most", + "start": 124070, + "end": 124310, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "vulnerable?", + "start": 124310, + "end": 124949, + "confidence": 1, + "speaker": "A" + }, + { + "text": "I", + "start": 124949, + "end": 125230, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "noticed", + "start": 125230, + "end": 125510, + "confidence": 0.882487, + "speaker": "A" + }, + { + "text": "that", + "start": 125510, + "end": 125630, + "confidence": 0.97998047, + "speaker": "A" + }, + { + "text": "in", + "start": 125630, + "end": 125750, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "New", + "start": 125750, + "end": 125870, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "York", + "start": 125870, + "end": 126030, + "confidence": 1, + "speaker": "A" + }, + { + "text": "City,", + "start": 126030, + "end": 126190, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "for", + "start": 126190, + "end": 126350, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "example,", + "start": 126350, + "end": 126750, + "confidence": 0.96435547, + "speaker": "A" + }, + { + "text": "they're", + "start": 126750, + "end": 127190, + "confidence": 0.9485677, + "speaker": "A" + }, + { + "text": "canceling", + "start": 127190, + "end": 127790, + "confidence": 0.87597656, + "speaker": "A" + }, + { + "text": "outdoor", + "start": 127790, + "end": 128190, + "confidence": 0.9984131, + "speaker": "A" + }, + { + "text": "activities.", + "start": 128190, + "end": 128670, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "And", + "start": 128670, + "end": 128990, + "confidence": 0.9458008, + "speaker": "A" + }, + { + "text": "so", + "start": 128990, + "end": 129230, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "here", + "start": 129230, + "end": 129390, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "it", + "start": 129390, + "end": 129510, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "is", + "start": 129510, + "end": 129630, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "in", + "start": 129630, + "end": 129910, + "confidence": 0.94921875, + "speaker": "A" + }, + { + "text": "the", + "start": 130070, + "end": 130470, + "confidence": 0.85595703, + "speaker": "A" + }, + { + "text": "early", + "start": 130550, + "end": 130830, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "days", + "start": 130830, + "end": 130990, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 130990, + "end": 131150, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "summer", + "start": 131150, + "end": 131390, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "and", + "start": 131390, + "end": 131510, + "confidence": 0.9663086, + "speaker": "A" + }, + { + "text": "they", + "start": 131510, + "end": 131630, + "confidence": 0.9296875, + "speaker": "A" + }, + { + "text": "have", + "start": 131630, + "end": 131750, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "to", + "start": 131750, + "end": 131830, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "keep", + "start": 131830, + "end": 131950, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "all", + "start": 131950, + "end": 132110, + "confidence": 0.9970703, + "speaker": "A" + }, + { + "text": "the", + "start": 132110, + "end": 132230, + "confidence": 0.9902344, + "speaker": "A" + }, + { + "text": "kids", + "start": 132230, + "end": 132470, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "inside.", + "start": 132470, + "end": 132950, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "So", + "start": 132950, + "end": 133350, + "confidence": 0.95214844, + "speaker": "A" + }, + { + "text": "who", + "start": 133350, + "end": 133670, + "confidence": 1, + "speaker": "A" + }, + { + "text": "tends", + "start": 133670, + "end": 133950, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "to", + "start": 133950, + "end": 134110, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "be", + "start": 134110, + "end": 134270, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "vulnerable", + "start": 134270, + "end": 134670, + "confidence": 1, + "speaker": "A" + }, + { + "text": "in", + "start": 134670, + "end": 134830, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "a", + "start": 134830, + "end": 134990, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "situation", + "start": 134990, + "end": 135430, + "confidence": 1, + "speaker": "A" + }, + { + "text": "like", + "start": 135510, + "end": 135750, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "this?", + "start": 135750, + "end": 135990, + "confidence": 0.99658203, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "It's the youngest. So children, obviously, whose bodies are still developing, the elderly who are, you know, their bodies are more in decline and they're more susceptible to the health impacts of breathing, the poor air quality. And then people who have pre existing health conditions, people with respiratory conditions or heart conditions, can be triggered by high levels of air pollution.", + "confidence": 0.95734787, + "start": 137610, + "end": 156650, + "words": [ + { + "text": "It's", + "start": 137610, + "end": 137930, + "confidence": 0.9005534, + "speaker": "B" + }, + { + "text": "the", + "start": 137930, + "end": 138250, + "confidence": 0.5307617, + "speaker": "B" + }, + { + "text": "youngest.", + "start": 138250, + "end": 138810, + "confidence": 0.9851074, + "speaker": "B" + }, + { + "text": "So", + "start": 138810, + "end": 139090, + "confidence": 0.6489258, + "speaker": "B" + }, + { + "text": "children,", + "start": 139090, + "end": 139330, + "confidence": 1, + "speaker": "B" + }, + { + "text": "obviously,", + "start": 139330, + "end": 140010, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "whose", + "start": 140890, + "end": 141450, + "confidence": 0.79467773, + "speaker": "B" + }, + { + "text": "bodies", + "start": 141450, + "end": 141730, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "are", + "start": 141730, + "end": 141850, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "still", + "start": 141850, + "end": 141970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "developing,", + "start": 141970, + "end": 142450, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 142450, + "end": 142730, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "elderly", + "start": 142730, + "end": 143250, + "confidence": 1, + "speaker": "B" + }, + { + "text": "who", + "start": 143250, + "end": 143530, + "confidence": 0.89160156, + "speaker": "B" + }, + { + "text": "are,", + "start": 143530, + "end": 143810, + "confidence": 0.70458984, + "speaker": "B" + }, + { + "text": "you", + "start": 143810, + "end": 144010, + "confidence": 0.5307617, + "speaker": "B" + }, + { + "text": "know,", + "start": 144010, + "end": 144170, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "their", + "start": 144170, + "end": 144370, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "bodies", + "start": 144370, + "end": 144570, + "confidence": 0.9996745, + "speaker": "B" + }, + { + "text": "are", + "start": 144570, + "end": 144690, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "more", + "start": 144690, + "end": 144850, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "in", + "start": 144850, + "end": 144970, + "confidence": 0.96435547, + "speaker": "B" + }, + { + "text": "decline", + "start": 144970, + "end": 145250, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "and", + "start": 145250, + "end": 145410, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "they're", + "start": 145410, + "end": 145610, + "confidence": 0.9921875, + "speaker": "B" + }, + { + "text": "more", + "start": 145610, + "end": 145730, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "susceptible", + "start": 145730, + "end": 146250, + "confidence": 0.99960935, + "speaker": "B" + }, + { + "text": "to", + "start": 146250, + "end": 146450, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 146450, + "end": 146570, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "health", + "start": 146570, + "end": 146770, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "impacts", + "start": 146770, + "end": 147250, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "of", + "start": 147250, + "end": 147530, + "confidence": 0.95751953, + "speaker": "B" + }, + { + "text": "breathing,", + "start": 147690, + "end": 148130, + "confidence": 0.95426434, + "speaker": "B" + }, + { + "text": "the", + "start": 148130, + "end": 148410, + "confidence": 0.7241211, + "speaker": "B" + }, + { + "text": "poor", + "start": 148490, + "end": 148810, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "air", + "start": 148810, + "end": 148970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "quality.", + "start": 148970, + "end": 149450, + "confidence": 1, + "speaker": "B" + }, + { + "text": "And", + "start": 150570, + "end": 150850, + "confidence": 0.8666992, + "speaker": "B" + }, + { + "text": "then", + "start": 150850, + "end": 151050, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "people", + "start": 151050, + "end": 151290, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "who", + "start": 151290, + "end": 151490, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "have", + "start": 151490, + "end": 151610, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "pre", + "start": 151610, + "end": 151770, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "existing", + "start": 151770, + "end": 152169, + "confidence": 0.98828125, + "speaker": "B" + }, + { + "text": "health", + "start": 152169, + "end": 152369, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "conditions,", + "start": 152369, + "end": 152650, + "confidence": 0.9987793, + "speaker": "B" + }, + { + "text": "people", + "start": 152650, + "end": 152850, + "confidence": 0.9707031, + "speaker": "B" + }, + { + "text": "with", + "start": 152850, + "end": 153010, + "confidence": 0.9951172, + "speaker": "B" + }, + { + "text": "respiratory", + "start": 153010, + "end": 153410, + "confidence": 0.9978841, + "speaker": "B" + }, + { + "text": "conditions", + "start": 153410, + "end": 153770, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "or", + "start": 153770, + "end": 153970, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "heart", + "start": 153970, + "end": 154130, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "conditions,", + "start": 154130, + "end": 154490, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "can", + "start": 154490, + "end": 154690, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "be", + "start": 154690, + "end": 154850, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "triggered", + "start": 154850, + "end": 155210, + "confidence": 1, + "speaker": "B" + }, + { + "text": "by", + "start": 155210, + "end": 155370, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "high", + "start": 155370, + "end": 155610, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "levels", + "start": 155610, + "end": 155850, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "of", + "start": 155850, + "end": 155970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "air", + "start": 155970, + "end": 156170, + "confidence": 1, + "speaker": "B" + }, + { + "text": "pollution.", + "start": 156170, + "end": 156650, + "confidence": 1, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "Could this get worse?", + "confidence": 0.9994507, + "start": 157450, + "end": 158650, + "words": [ + { + "text": "Could", + "start": 157450, + "end": 157770, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "this", + "start": 157770, + "end": 158010, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "get", + "start": 158010, + "end": 158210, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "worse?", + "start": 158210, + "end": 158650, + "confidence": 0.99975586, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "That's a good question. I mean, I think if in some areas it's much worse than others and it just depends on kind of where the smoke is concentrated. I think New York has some of the higher concentrations right now, but that's going to change as that air moves away from the New York area. But over the course of the next few days, we will see different areas being hit at different times with the highest concentrations.", + "confidence": 0.9877186, + "start": 162170, + "end": 183420, + "words": [ + { + "text": "That's", + "start": 162170, + "end": 162490, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 162490, + "end": 162610, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "good", + "start": 162610, + "end": 162770, + "confidence": 1, + "speaker": "B" + }, + { + "text": "question.", + "start": 162770, + "end": 163050, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "I", + "start": 163130, + "end": 163410, + "confidence": 0.93896484, + "speaker": "B" + }, + { + "text": "mean,", + "start": 163410, + "end": 163570, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "I", + "start": 163570, + "end": 163690, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "think", + "start": 163690, + "end": 163850, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "if", + "start": 163850, + "end": 164170, + "confidence": 0.98779297, + "speaker": "B" + }, + { + "text": "in", + "start": 165260, + "end": 165380, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "some", + "start": 165380, + "end": 165540, + "confidence": 1, + "speaker": "B" + }, + { + "text": "areas", + "start": 165540, + "end": 165820, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "it's", + "start": 165900, + "end": 166220, + "confidence": 0.99820966, + "speaker": "B" + }, + { + "text": "much", + "start": 166220, + "end": 166340, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "worse", + "start": 166340, + "end": 166540, + "confidence": 1, + "speaker": "B" + }, + { + "text": "than", + "start": 166540, + "end": 166660, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "others", + "start": 166660, + "end": 166860, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 166860, + "end": 167180, + "confidence": 0.97314453, + "speaker": "B" + }, + { + "text": "it", + "start": 167180, + "end": 167460, + "confidence": 0.99121094, + "speaker": "B" + }, + { + "text": "just", + "start": 167460, + "end": 167620, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "depends", + "start": 167620, + "end": 167980, + "confidence": 0.90201825, + "speaker": "B" + }, + { + "text": "on", + "start": 167980, + "end": 168180, + "confidence": 0.9951172, + "speaker": "B" + }, + { + "text": "kind", + "start": 168180, + "end": 168340, + "confidence": 0.79785156, + "speaker": "B" + }, + { + "text": "of", + "start": 168340, + "end": 168500, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "where", + "start": 168500, + "end": 168700, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 168700, + "end": 168860, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "smoke", + "start": 168860, + "end": 169140, + "confidence": 0.9503581, + "speaker": "B" + }, + { + "text": "is", + "start": 169140, + "end": 169340, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "concentrated.", + "start": 169340, + "end": 170140, + "confidence": 0.99990237, + "speaker": "B" + }, + { + "text": "I", + "start": 171020, + "end": 171300, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "think", + "start": 171300, + "end": 171460, + "confidence": 1, + "speaker": "B" + }, + { + "text": "New", + "start": 171460, + "end": 171620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "York", + "start": 171620, + "end": 171900, + "confidence": 1, + "speaker": "B" + }, + { + "text": "has", + "start": 171980, + "end": 172260, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "some", + "start": 172260, + "end": 172420, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 172420, + "end": 172540, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 172540, + "end": 172660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "higher", + "start": 172660, + "end": 172860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "concentrations", + "start": 172860, + "end": 173540, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "right", + "start": 173540, + "end": 173700, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "now,", + "start": 173700, + "end": 173860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "but", + "start": 173860, + "end": 174020, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "that's", + "start": 174020, + "end": 174220, + "confidence": 0.9983724, + "speaker": "B" + }, + { + "text": "going", + "start": 174220, + "end": 174340, + "confidence": 0.7973633, + "speaker": "B" + }, + { + "text": "to", + "start": 174340, + "end": 174460, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "change", + "start": 174460, + "end": 174620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "as", + "start": 174620, + "end": 174820, + "confidence": 0.99121094, + "speaker": "B" + }, + { + "text": "that", + "start": 174820, + "end": 174980, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "air", + "start": 174980, + "end": 175180, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "moves", + "start": 175180, + "end": 175500, + "confidence": 1, + "speaker": "B" + }, + { + "text": "away", + "start": 175500, + "end": 175660, + "confidence": 1, + "speaker": "B" + }, + { + "text": "from", + "start": 175660, + "end": 175860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 175860, + "end": 175980, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "New", + "start": 175980, + "end": 176100, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "York", + "start": 176100, + "end": 176300, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "area.", + "start": 176300, + "end": 176620, + "confidence": 1, + "speaker": "B" + }, + { + "text": "But", + "start": 177100, + "end": 177380, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "over", + "start": 177380, + "end": 177540, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 177540, + "end": 177660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "course", + "start": 177660, + "end": 177780, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 177780, + "end": 177900, + "confidence": 0.82958984, + "speaker": "B" + }, + { + "text": "the", + "start": 177900, + "end": 177980, + "confidence": 0.9667969, + "speaker": "B" + }, + { + "text": "next", + "start": 177980, + "end": 178100, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "few", + "start": 178100, + "end": 178300, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "days,", + "start": 178300, + "end": 178500, + "confidence": 1, + "speaker": "B" + }, + { + "text": "we", + "start": 178500, + "end": 178660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "will", + "start": 178660, + "end": 178860, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "see", + "start": 178860, + "end": 179180, + "confidence": 1, + "speaker": "B" + }, + { + "text": "different", + "start": 179580, + "end": 179940, + "confidence": 1, + "speaker": "B" + }, + { + "text": "areas", + "start": 179940, + "end": 180220, + "confidence": 1, + "speaker": "B" + }, + { + "text": "being", + "start": 180220, + "end": 180539, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hit", + "start": 180539, + "end": 180940, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "at", + "start": 180940, + "end": 181220, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "different", + "start": 181220, + "end": 181460, + "confidence": 1, + "speaker": "B" + }, + { + "text": "times", + "start": 181460, + "end": 181820, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "with", + "start": 181980, + "end": 182260, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 182260, + "end": 182380, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "highest", + "start": 182380, + "end": 182660, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "concentrations.", + "start": 182660, + "end": 183420, + "confidence": 0.998291, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "I was going to ask you about.", + "confidence": 0.9385463, + "start": 183740, + "end": 184660, + "words": [ + { + "text": "I", + "start": 183740, + "end": 183980, + "confidence": 0.9140625, + "speaker": "A" + }, + { + "text": "was", + "start": 183980, + "end": 184100, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "going", + "start": 184100, + "end": 184220, + "confidence": 0.96484375, + "speaker": "A" + }, + { + "text": "to", + "start": 184220, + "end": 184300, + "confidence": 0.9897461, + "speaker": "A" + }, + { + "text": "ask", + "start": 184300, + "end": 184380, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "you", + "start": 184380, + "end": 184460, + "confidence": 0.86083984, + "speaker": "A" + }, + { + "text": "about.", + "start": 184460, + "end": 184660, + "confidence": 0.84472656, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "More fires start burning. I don't expect the concentrations to go up too much higher.", + "confidence": 0.9550103, + "start": 184660, + "end": 189020, + "words": [ + { + "text": "More", + "start": 184660, + "end": 184900, + "confidence": 0.57958984, + "speaker": "B" + }, + { + "text": "fires", + "start": 184900, + "end": 185220, + "confidence": 0.8249512, + "speaker": "B" + }, + { + "text": "start", + "start": 185220, + "end": 185380, + "confidence": 0.94628906, + "speaker": "B" + }, + { + "text": "burning.", + "start": 185380, + "end": 185660, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "I", + "start": 185660, + "end": 185860, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "don't", + "start": 185860, + "end": 186060, + "confidence": 0.9998372, + "speaker": "B" + }, + { + "text": "expect", + "start": 186060, + "end": 186300, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 186940, + "end": 187220, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "concentrations", + "start": 187220, + "end": 187780, + "confidence": 0.99890137, + "speaker": "B" + }, + { + "text": "to", + "start": 187780, + "end": 187900, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "go", + "start": 187900, + "end": 188020, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "up", + "start": 188020, + "end": 188300, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "too", + "start": 188300, + "end": 188580, + "confidence": 0.98583984, + "speaker": "B" + }, + { + "text": "much", + "start": 188580, + "end": 188740, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "higher.", + "start": 188740, + "end": 189020, + "confidence": 0.99902344, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "I was going to ask you how and you started to answer this, but how much longer could this last? Forgive me if I'm asking you to speculate, but what do you think?", + "confidence": 0.97967714, + "start": 189100, + "end": 196220, + "words": [ + { + "text": "I", + "start": 189100, + "end": 189340, + "confidence": 0.99609375, + "speaker": "A" + }, + { + "text": "was", + "start": 189340, + "end": 189420, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "going", + "start": 189420, + "end": 189540, + "confidence": 0.97998047, + "speaker": "A" + }, + { + "text": "to", + "start": 189540, + "end": 189660, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "ask", + "start": 189660, + "end": 189780, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "you", + "start": 189780, + "end": 189940, + "confidence": 0.9819336, + "speaker": "A" + }, + { + "text": "how", + "start": 189940, + "end": 190100, + "confidence": 0.7294922, + "speaker": "A" + }, + { + "text": "and", + "start": 190100, + "end": 190260, + "confidence": 0.94677734, + "speaker": "A" + }, + { + "text": "you", + "start": 190260, + "end": 190420, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "started", + "start": 190420, + "end": 190620, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "to", + "start": 190620, + "end": 190780, + "confidence": 0.9404297, + "speaker": "A" + }, + { + "text": "answer", + "start": 190780, + "end": 190980, + "confidence": 0.96809894, + "speaker": "A" + }, + { + "text": "this,", + "start": 190980, + "end": 191140, + "confidence": 0.99560547, + "speaker": "A" + }, + { + "text": "but", + "start": 191140, + "end": 191420, + "confidence": 0.9013672, + "speaker": "A" + }, + { + "text": "how", + "start": 191420, + "end": 191700, + "confidence": 1, + "speaker": "A" + }, + { + "text": "much", + "start": 191700, + "end": 191940, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "longer", + "start": 191940, + "end": 192420, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "could", + "start": 192420, + "end": 192700, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "this", + "start": 192700, + "end": 192940, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "last?", + "start": 192940, + "end": 193260, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Forgive", + "start": 193420, + "end": 193820, + "confidence": 0.99934894, + "speaker": "A" + }, + { + "text": "me", + "start": 193820, + "end": 193900, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "if", + "start": 193900, + "end": 193980, + "confidence": 0.98095703, + "speaker": "A" + }, + { + "text": "I'm", + "start": 193980, + "end": 194140, + "confidence": 0.9920247, + "speaker": "A" + }, + { + "text": "asking", + "start": 194140, + "end": 194300, + "confidence": 1, + "speaker": "A" + }, + { + "text": "you", + "start": 194300, + "end": 194380, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "to", + "start": 194380, + "end": 194500, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "speculate,", + "start": 194500, + "end": 194900, + "confidence": 1, + "speaker": "A" + }, + { + "text": "but", + "start": 194900, + "end": 195180, + "confidence": 0.953125, + "speaker": "A" + }, + { + "text": "what", + "start": 195340, + "end": 195620, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "do", + "start": 195620, + "end": 195780, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "you", + "start": 195780, + "end": 195940, + "confidence": 0.9946289, + "speaker": "A" + }, + { + "text": "think?", + "start": 195940, + "end": 196220, + "confidence": 0.9980469, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "Well, I think the fires are going to burn for a little bit longer. But the key for us in the US Is the weather system changing. Right now it's the weather systems that are pulling that air into our Mid Atlantic and Northeast region. As those weather systems change and shift, we'll see that smoke going elsewhere and not impact us in this region as much. I think that's going to be the defining factor. I think the next couple days we're going to see a shift in that weather pattern and start to push the smoke away from where we are.", + "confidence": 0.9817744, + "start": 198280, + "end": 227480, + "words": [ + { + "text": "Well,", + "start": 198280, + "end": 198400, + "confidence": 0.9091797, + "speaker": "B" + }, + { + "text": "I", + "start": 198400, + "end": 198520, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "think", + "start": 198520, + "end": 198640, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 198640, + "end": 198760, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "fires", + "start": 198760, + "end": 199080, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "are", + "start": 199080, + "end": 199160, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "going", + "start": 199160, + "end": 199280, + "confidence": 0.67089844, + "speaker": "B" + }, + { + "text": "to", + "start": 199280, + "end": 199400, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "burn", + "start": 199400, + "end": 199560, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "for", + "start": 199560, + "end": 199680, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 199680, + "end": 199800, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "little", + "start": 199800, + "end": 199920, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "bit", + "start": 199920, + "end": 200080, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "longer.", + "start": 200080, + "end": 200440, + "confidence": 1, + "speaker": "B" + }, + { + "text": "But", + "start": 200440, + "end": 200640, + "confidence": 0.98876953, + "speaker": "B" + }, + { + "text": "the", + "start": 200640, + "end": 200840, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "key", + "start": 200840, + "end": 201120, + "confidence": 1, + "speaker": "B" + }, + { + "text": "for", + "start": 201120, + "end": 201400, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "us", + "start": 201400, + "end": 201640, + "confidence": 1, + "speaker": "B" + }, + { + "text": "in", + "start": 201640, + "end": 201800, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 201800, + "end": 201920, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "US", + "start": 201920, + "end": 202200, + "confidence": 0.98876953, + "speaker": "B" + }, + { + "text": "Is", + "start": 202200, + "end": 202480, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 202480, + "end": 202680, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "weather", + "start": 202680, + "end": 203000, + "confidence": 1, + "speaker": "B" + }, + { + "text": "system", + "start": 203000, + "end": 203280, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "changing.", + "start": 203280, + "end": 203800, + "confidence": 0.98828125, + "speaker": "B" + }, + { + "text": "Right", + "start": 203960, + "end": 204280, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "now", + "start": 204280, + "end": 204600, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "it's", + "start": 204680, + "end": 205080, + "confidence": 0.98258466, + "speaker": "B" + }, + { + "text": "the", + "start": 205080, + "end": 205280, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "weather", + "start": 205280, + "end": 205520, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "systems", + "start": 205520, + "end": 205840, + "confidence": 0.9987793, + "speaker": "B" + }, + { + "text": "that", + "start": 205840, + "end": 205960, + "confidence": 0.9941406, + "speaker": "B" + }, + { + "text": "are", + "start": 205960, + "end": 206080, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "pulling", + "start": 206080, + "end": 206320, + "confidence": 0.9996745, + "speaker": "B" + }, + { + "text": "that", + "start": 206320, + "end": 206480, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "air", + "start": 206480, + "end": 206760, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "into", + "start": 207320, + "end": 207640, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "our", + "start": 207640, + "end": 207960, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "Mid", + "start": 209080, + "end": 209400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "Atlantic", + "start": 209400, + "end": 209920, + "confidence": 0.88134766, + "speaker": "B" + }, + { + "text": "and", + "start": 209920, + "end": 210160, + "confidence": 0.87353516, + "speaker": "B" + }, + { + "text": "Northeast", + "start": 210160, + "end": 210720, + "confidence": 0.99886066, + "speaker": "B" + }, + { + "text": "region.", + "start": 210720, + "end": 211000, + "confidence": 1, + "speaker": "B" + }, + { + "text": "As", + "start": 211080, + "end": 211360, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "those", + "start": 211360, + "end": 211560, + "confidence": 0.9609375, + "speaker": "B" + }, + { + "text": "weather", + "start": 211560, + "end": 211960, + "confidence": 0.99194336, + "speaker": "B" + }, + { + "text": "systems", + "start": 212920, + "end": 213480, + "confidence": 0.99780273, + "speaker": "B" + }, + { + "text": "change", + "start": 213480, + "end": 213720, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 213720, + "end": 213960, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "shift,", + "start": 213960, + "end": 214360, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "we'll", + "start": 214520, + "end": 214840, + "confidence": 0.9785156, + "speaker": "B" + }, + { + "text": "see", + "start": 214840, + "end": 214960, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "that", + "start": 214960, + "end": 215120, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "smoke", + "start": 215120, + "end": 215400, + "confidence": 0.9900716, + "speaker": "B" + }, + { + "text": "going", + "start": 215400, + "end": 215640, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "elsewhere", + "start": 215640, + "end": 216120, + "confidence": 0.977417, + "speaker": "B" + }, + { + "text": "and", + "start": 216600, + "end": 216880, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "not", + "start": 216880, + "end": 217080, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "impact", + "start": 217080, + "end": 217400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "us", + "start": 217400, + "end": 217800, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "in", + "start": 217880, + "end": 218160, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "this", + "start": 218160, + "end": 218360, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "region", + "start": 218360, + "end": 218640, + "confidence": 1, + "speaker": "B" + }, + { + "text": "as", + "start": 218640, + "end": 218880, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "much.", + "start": 218880, + "end": 219160, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "I", + "start": 219320, + "end": 219560, + "confidence": 0.9736328, + "speaker": "B" + }, + { + "text": "think", + "start": 219560, + "end": 219680, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "that's", + "start": 219680, + "end": 219960, + "confidence": 0.9938151, + "speaker": "B" + }, + { + "text": "going", + "start": 219960, + "end": 220040, + "confidence": 0.9824219, + "speaker": "B" + }, + { + "text": "to", + "start": 220040, + "end": 220120, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "be", + "start": 220120, + "end": 220240, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "the", + "start": 220240, + "end": 220400, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "defining", + "start": 220400, + "end": 220760, + "confidence": 1, + "speaker": "B" + }, + { + "text": "factor.", + "start": 220760, + "end": 221080, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "I", + "start": 221080, + "end": 221240, + "confidence": 0.97314453, + "speaker": "B" + }, + { + "text": "think", + "start": 221240, + "end": 221360, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 221360, + "end": 221480, + "confidence": 0.9902344, + "speaker": "B" + }, + { + "text": "next", + "start": 221480, + "end": 221600, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "couple", + "start": 221600, + "end": 221840, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "days", + "start": 221840, + "end": 222000, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "we're", + "start": 222000, + "end": 222200, + "confidence": 0.98844403, + "speaker": "B" + }, + { + "text": "going", + "start": 222200, + "end": 222320, + "confidence": 0.67578125, + "speaker": "B" + }, + { + "text": "to", + "start": 222320, + "end": 222600, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "see", + "start": 222600, + "end": 222880, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "a", + "start": 222880, + "end": 223040, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "shift", + "start": 223040, + "end": 223400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "in", + "start": 224120, + "end": 224400, + "confidence": 0.99560547, + "speaker": "B" + }, + { + "text": "that", + "start": 224400, + "end": 224560, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "weather", + "start": 224560, + "end": 224800, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "pattern", + "start": 224800, + "end": 225120, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 225120, + "end": 225360, + "confidence": 0.99609375, + "speaker": "B" + }, + { + "text": "start", + "start": 225360, + "end": 225520, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "to", + "start": 225520, + "end": 225640, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "push", + "start": 225640, + "end": 225800, + "confidence": 1, + "speaker": "B" + }, + { + "text": "the", + "start": 225800, + "end": 225920, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "smoke", + "start": 225920, + "end": 226160, + "confidence": 0.8540039, + "speaker": "B" + }, + { + "text": "away", + "start": 226160, + "end": 226400, + "confidence": 1, + "speaker": "B" + }, + { + "text": "from", + "start": 226400, + "end": 226760, + "confidence": 0.6513672, + "speaker": "B" + }, + { + "text": "where", + "start": 226760, + "end": 227040, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "we", + "start": 227040, + "end": 227200, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "are.", + "start": 227200, + "end": 227480, + "confidence": 0.99853516, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "And finally, with the impacts of climate change, we are seeing more wildfires. Will we be seeing more of these kinds of wide ranging air quality consequences or circumstances?", + "confidence": 0.9881684, + "start": 227930, + "end": 239850, + "words": [ + { + "text": "And", + "start": 227930, + "end": 228050, + "confidence": 0.9433594, + "speaker": "A" + }, + { + "text": "finally,", + "start": 228050, + "end": 228410, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "with", + "start": 228410, + "end": 228650, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "the", + "start": 228650, + "end": 228930, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "impacts", + "start": 228930, + "end": 229370, + "confidence": 0.9921875, + "speaker": "A" + }, + { + "text": "of", + "start": 229370, + "end": 229530, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "climate", + "start": 229530, + "end": 229890, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "change,", + "start": 229890, + "end": 230210, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "we", + "start": 230210, + "end": 230450, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "are", + "start": 230450, + "end": 230650, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "seeing", + "start": 230650, + "end": 230970, + "confidence": 1, + "speaker": "A" + }, + { + "text": "more", + "start": 230970, + "end": 231290, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "wildfires.", + "start": 231290, + "end": 232250, + "confidence": 0.9993164, + "speaker": "A" + }, + { + "text": "Will", + "start": 232410, + "end": 232730, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "we", + "start": 232730, + "end": 232970, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "be", + "start": 232970, + "end": 233210, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "seeing", + "start": 233210, + "end": 233610, + "confidence": 0.99975586, + "speaker": "A" + }, + { + "text": "more", + "start": 233690, + "end": 234050, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 234050, + "end": 234290, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "these", + "start": 234290, + "end": 234530, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "kinds", + "start": 234530, + "end": 234890, + "confidence": 0.9914551, + "speaker": "A" + }, + { + "text": "of", + "start": 234890, + "end": 235130, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "wide", + "start": 235450, + "end": 235850, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "ranging", + "start": 235850, + "end": 236410, + "confidence": 0.9998372, + "speaker": "A" + }, + { + "text": "air", + "start": 237290, + "end": 237610, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "quality", + "start": 237610, + "end": 238050, + "confidence": 1, + "speaker": "A" + }, + { + "text": "consequences", + "start": 238050, + "end": 238690, + "confidence": 0.9385742, + "speaker": "A" + }, + { + "text": "or", + "start": 238690, + "end": 239050, + "confidence": 0.87841797, + "speaker": "A" + }, + { + "text": "circumstances?", + "start": 239130, + "end": 239850, + "confidence": 0.93204755, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "I mean, that is one of the predictions for climate change. Looking into the future, the fire season is starting earlier and lasting longer and we're seeing more frequent fires. So yeah, this is probably something that we'll be seeing more, more frequently. This tends to be much more of an issue in the western U.S. so the eastern U.S. getting hit right now is a little bit new. But yeah, I think with climate change moving forward, this is something that is going to happen more frequently.", + "confidence": 0.9763954, + "start": 241370, + "end": 267570, + "words": [ + { + "text": "I", + "start": 241370, + "end": 241650, + "confidence": 0.9238281, + "speaker": "B" + }, + { + "text": "mean,", + "start": 241650, + "end": 241810, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "that", + "start": 241810, + "end": 241930, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "is", + "start": 241930, + "end": 242090, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "one", + "start": 242090, + "end": 242250, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 242250, + "end": 242330, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 242330, + "end": 242450, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "predictions", + "start": 242450, + "end": 243050, + "confidence": 0.8977051, + "speaker": "B" + }, + { + "text": "for", + "start": 243050, + "end": 243450, + "confidence": 0.73095703, + "speaker": "B" + }, + { + "text": "climate", + "start": 244490, + "end": 244890, + "confidence": 1, + "speaker": "B" + }, + { + "text": "change.", + "start": 244890, + "end": 245130, + "confidence": 1, + "speaker": "B" + }, + { + "text": "Looking", + "start": 245130, + "end": 245370, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "into", + "start": 245370, + "end": 245570, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "the", + "start": 245570, + "end": 245730, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "future,", + "start": 245730, + "end": 246010, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "the", + "start": 246410, + "end": 246730, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "fire", + "start": 246730, + "end": 247010, + "confidence": 1, + "speaker": "B" + }, + { + "text": "season", + "start": 247010, + "end": 247290, + "confidence": 1, + "speaker": "B" + }, + { + "text": "is", + "start": 247290, + "end": 247490, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "starting", + "start": 247490, + "end": 247730, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "earlier", + "start": 247730, + "end": 247970, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "and", + "start": 247970, + "end": 248210, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "lasting", + "start": 248210, + "end": 248570, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "longer", + "start": 248570, + "end": 249050, + "confidence": 1, + "speaker": "B" + }, + { + "text": "and", + "start": 249610, + "end": 249890, + "confidence": 0.9736328, + "speaker": "B" + }, + { + "text": "we're", + "start": 249890, + "end": 250090, + "confidence": 0.93815106, + "speaker": "B" + }, + { + "text": "seeing", + "start": 250090, + "end": 250290, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "more", + "start": 250290, + "end": 250450, + "confidence": 1, + "speaker": "B" + }, + { + "text": "frequent", + "start": 250450, + "end": 250810, + "confidence": 0.99975586, + "speaker": "B" + }, + { + "text": "fires.", + "start": 250810, + "end": 251290, + "confidence": 0.98950195, + "speaker": "B" + }, + { + "text": "So", + "start": 251290, + "end": 251610, + "confidence": 0.94628906, + "speaker": "B" + }, + { + "text": "yeah,", + "start": 252010, + "end": 252370, + "confidence": 0.9715169, + "speaker": "B" + }, + { + "text": "this", + "start": 252370, + "end": 252530, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "is", + "start": 252530, + "end": 252690, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "probably", + "start": 252690, + "end": 252970, + "confidence": 0.9973958, + "speaker": "B" + }, + { + "text": "something", + "start": 252970, + "end": 253290, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "that", + "start": 253290, + "end": 253690, + "confidence": 0.9863281, + "speaker": "B" + }, + { + "text": "we'll", + "start": 253770, + "end": 254090, + "confidence": 0.9835612, + "speaker": "B" + }, + { + "text": "be", + "start": 254090, + "end": 254210, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "seeing", + "start": 254210, + "end": 254530, + "confidence": 0.9992676, + "speaker": "B" + }, + { + "text": "more,", + "start": 254530, + "end": 254780, + "confidence": 0.5083008, + "speaker": "B" + }, + { + "text": "more", + "start": 254930, + "end": 255050, + "confidence": 0.8666992, + "speaker": "B" + }, + { + "text": "frequently.", + "start": 255050, + "end": 255570, + "confidence": 1, + "speaker": "B" + }, + { + "text": "This", + "start": 255650, + "end": 255930, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "tends", + "start": 255930, + "end": 256170, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "to", + "start": 256170, + "end": 256290, + "confidence": 1, + "speaker": "B" + }, + { + "text": "be", + "start": 256290, + "end": 256410, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "much", + "start": 256410, + "end": 256570, + "confidence": 0.9916992, + "speaker": "B" + }, + { + "text": "more", + "start": 256570, + "end": 256690, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "of", + "start": 256690, + "end": 256770, + "confidence": 0.9970703, + "speaker": "B" + }, + { + "text": "an", + "start": 256770, + "end": 256890, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "issue", + "start": 256890, + "end": 257090, + "confidence": 1, + "speaker": "B" + }, + { + "text": "in", + "start": 257090, + "end": 257250, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "the", + "start": 257250, + "end": 257330, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "western", + "start": 257330, + "end": 257610, + "confidence": 1, + "speaker": "B" + }, + { + "text": "U.S.", + "start": 257610, + "end": 257890, + "confidence": 0.99023, + "speaker": "B" + }, + { + "text": "so", + "start": 258130, + "end": 258410, + "confidence": 0.75439453, + "speaker": "B" + }, + { + "text": "the", + "start": 258410, + "end": 258530, + "confidence": 0.9975586, + "speaker": "B" + }, + { + "text": "eastern", + "start": 258530, + "end": 258770, + "confidence": 0.9916992, + "speaker": "B" + }, + { + "text": "U.S.", + "start": 258770, + "end": 259050, + "confidence": 0.99121, + "speaker": "B" + }, + { + "text": "getting", + "start": 259050, + "end": 259290, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "hit", + "start": 259290, + "end": 259490, + "confidence": 0.99658203, + "speaker": "B" + }, + { + "text": "right", + "start": 259490, + "end": 259690, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "now", + "start": 259690, + "end": 259970, + "confidence": 1, + "speaker": "B" + }, + { + "text": "is", + "start": 260370, + "end": 260690, + "confidence": 0.99316406, + "speaker": "B" + }, + { + "text": "a", + "start": 260690, + "end": 260850, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "little", + "start": 260850, + "end": 260970, + "confidence": 1, + "speaker": "B" + }, + { + "text": "bit", + "start": 260970, + "end": 261170, + "confidence": 0.99902344, + "speaker": "B" + }, + { + "text": "new.", + "start": 261170, + "end": 261490, + "confidence": 1, + "speaker": "B" + }, + { + "text": "But", + "start": 262210, + "end": 262530, + "confidence": 0.9819336, + "speaker": "B" + }, + { + "text": "yeah,", + "start": 262530, + "end": 262850, + "confidence": 0.97314453, + "speaker": "B" + }, + { + "text": "I", + "start": 262850, + "end": 263010, + "confidence": 0.9946289, + "speaker": "B" + }, + { + "text": "think", + "start": 263010, + "end": 263130, + "confidence": 1, + "speaker": "B" + }, + { + "text": "with", + "start": 263130, + "end": 263330, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "climate", + "start": 263330, + "end": 263650, + "confidence": 1, + "speaker": "B" + }, + { + "text": "change", + "start": 263650, + "end": 263930, + "confidence": 1, + "speaker": "B" + }, + { + "text": "moving", + "start": 263930, + "end": 264330, + "confidence": 1, + "speaker": "B" + }, + { + "text": "forward,", + "start": 264330, + "end": 264690, + "confidence": 1, + "speaker": "B" + }, + { + "text": "this", + "start": 264690, + "end": 264970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "is", + "start": 264970, + "end": 265130, + "confidence": 0.99853516, + "speaker": "B" + }, + { + "text": "something", + "start": 265130, + "end": 265330, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "that", + "start": 265330, + "end": 265650, + "confidence": 0.9951172, + "speaker": "B" + }, + { + "text": "is", + "start": 266130, + "end": 266410, + "confidence": 0.97558594, + "speaker": "B" + }, + { + "text": "going", + "start": 266410, + "end": 266530, + "confidence": 0.66503906, + "speaker": "B" + }, + { + "text": "to", + "start": 266530, + "end": 266610, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "happen", + "start": 266610, + "end": 266770, + "confidence": 1, + "speaker": "B" + }, + { + "text": "more", + "start": 266770, + "end": 266970, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "frequently.", + "start": 266970, + "end": 267570, + "confidence": 0.959668, + "speaker": "B" + } + ] + }, + { + "speaker": "A", + "text": "That's Peter DeCarlo, associate professor in the Department of Environmental Health and Engineering at Johns Hopkins University. Professor DeCarlo, thanks so much for joining us and sharing this expertise with us.", + "confidence": 0.9886564, + "start": 267970, + "end": 278210, + "words": [ + { + "text": "That's", + "start": 267970, + "end": 268290, + "confidence": 0.9977214, + "speaker": "A" + }, + { + "text": "Peter", + "start": 268290, + "end": 268610, + "confidence": 0.99780273, + "speaker": "A" + }, + { + "text": "DeCarlo,", + "start": 268610, + "end": 269290, + "confidence": 0.94775, + "speaker": "A" + }, + { + "text": "associate", + "start": 269290, + "end": 269730, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "professor", + "start": 269730, + "end": 270170, + "confidence": 1, + "speaker": "A" + }, + { + "text": "in", + "start": 270170, + "end": 270290, + "confidence": 0.99658203, + "speaker": "A" + }, + { + "text": "the", + "start": 270290, + "end": 270410, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Department", + "start": 270410, + "end": 270690, + "confidence": 1, + "speaker": "A" + }, + { + "text": "of", + "start": 270770, + "end": 271009, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Environmental", + "start": 271009, + "end": 271610, + "confidence": 0.9992676, + "speaker": "A" + }, + { + "text": "Health", + "start": 271610, + "end": 271850, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "and", + "start": 271850, + "end": 272090, + "confidence": 0.9980469, + "speaker": "A" + }, + { + "text": "Engineering", + "start": 272090, + "end": 272610, + "confidence": 1, + "speaker": "A" + }, + { + "text": "at", + "start": 272770, + "end": 273090, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "Johns", + "start": 273090, + "end": 273530, + "confidence": 0.9777832, + "speaker": "A" + }, + { + "text": "Hopkins", + "start": 273530, + "end": 274050, + "confidence": 1, + "speaker": "A" + }, + { + "text": "University.", + "start": 274130, + "end": 274530, + "confidence": 1, + "speaker": "A" + }, + { + "text": "Professor", + "start": 274610, + "end": 275130, + "confidence": 0.99902344, + "speaker": "A" + }, + { + "text": "DeCarlo,", + "start": 275130, + "end": 275650, + "confidence": 0.96191, + "speaker": "A" + }, + { + "text": "thanks", + "start": 275650, + "end": 275890, + "confidence": 0.9951172, + "speaker": "A" + }, + { + "text": "so", + "start": 275890, + "end": 275970, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "much", + "start": 275970, + "end": 276090, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "for", + "start": 276090, + "end": 276250, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "joining", + "start": 276250, + "end": 276490, + "confidence": 0.90201825, + "speaker": "A" + }, + { + "text": "us", + "start": 276490, + "end": 276650, + "confidence": 0.99853516, + "speaker": "A" + }, + { + "text": "and", + "start": 276650, + "end": 276810, + "confidence": 0.9926758, + "speaker": "A" + }, + { + "text": "sharing", + "start": 276810, + "end": 277050, + "confidence": 0.99731445, + "speaker": "A" + }, + { + "text": "this", + "start": 277050, + "end": 277250, + "confidence": 0.9975586, + "speaker": "A" + }, + { + "text": "expertise", + "start": 277250, + "end": 277730, + "confidence": 0.89729816, + "speaker": "A" + }, + { + "text": "with", + "start": 277730, + "end": 277930, + "confidence": 0.9995117, + "speaker": "A" + }, + { + "text": "us.", + "start": 277930, + "end": 278210, + "confidence": 0.9995117, + "speaker": "A" + } + ] + }, + { + "speaker": "B", + "text": "Thank you for having me.", + "confidence": 0.9977539, + "start": 279410, + "end": 280530, + "words": [ + { + "text": "Thank", + "start": 279410, + "end": 279770, + "confidence": 0.99365234, + "speaker": "B" + }, + { + "text": "you", + "start": 279770, + "end": 279930, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "for", + "start": 279930, + "end": 280050, + "confidence": 0.9995117, + "speaker": "B" + }, + { + "text": "having", + "start": 280050, + "end": 280210, + "confidence": 0.9980469, + "speaker": "B" + }, + { + "text": "me.", + "start": 280210, + "end": 280530, + "confidence": 0.9980469, + "speaker": "B" + } + ] + } + ], + "confidence": 0.97860795, + "audio_duration": 282, + "punctuate": true, + "format_text": true, + "dual_channel": false, + "webhook_url": null, + "webhook_status_code": null, + "webhook_auth": false, + "webhook_auth_header_name": null, + "speed_boost": false, + "auto_highlights_result": null, + "auto_highlights": false, + "audio_start_from": null, + "audio_end_at": null, + "word_boost": [], + "boost_param": null, + "prompt": null, + "keyterms_prompt": [], + "filter_profanity": false, + "redact_pii": false, + "redact_pii_audio": false, + "redact_pii_audio_quality": null, + "redact_pii_audio_options": null, + "redact_pii_policies": null, + "redact_pii_sub": null, + "speaker_labels": true, + "speaker_options": null, + "content_safety": false, + "iab_categories": false, + "content_safety_labels": { + "status": "unavailable", + "results": [], + "summary": {} + }, + "iab_categories_result": { + "status": "unavailable", + "results": [], + "summary": {} + }, + "language_detection": true, + "language_detection_options": null, + "language_detection_results": null, + "language_confidence_threshold": null, + "language_confidence": 0.9982, + "custom_spelling": null, + "throttled": false, + "auto_chapters": false, + "summarization": false, + "summary_type": null, + "summary_model": null, + "custom_topics": false, + "topics": [], + "speech_threshold": null, + "speech_model": null, + "speech_models": [ + "universal" + ], + "speech_model_used": "universal", + "chapters": null, + "disfluencies": false, + "entity_detection": false, + "sentiment_analysis": false, + "sentiment_analysis_results": null, + "entities": null, + "speakers_expected": null, + "summary": null, + "custom_topics_results": null, + "is_deleted": null, + "multichannel": null, + "project_id": 1448960, + "token_id": 1461435 +} \ No newline at end of file diff --git a/test/integration/transcriptionSummarizerTest.js b/test/integration/transcriptionSummarizerTest.js new file mode 100644 index 0000000..db2564d --- /dev/null +++ b/test/integration/transcriptionSummarizerTest.js @@ -0,0 +1,12 @@ +const fs = require('fs'); +const transSummarizer = require("../../services/modules/jsonTools/transcriptionSummarizer.js"); + +// JSON-Datei laden +const inputJson = JSON.parse(fs.readFileSync("./testFile.json", "utf8")); + +// Übergabe an den Summarizer +transSummarizer.function({ + inputJson: inputJson +}); + + From a0ed2ab7bdffecd1dd11b516aefee660bc9c936d Mon Sep 17 00:00:00 2001 From: Azeufack Noupeu Willy Date: Thu, 20 Nov 2025 14:05:52 +0100 Subject: [PATCH 15/37] feat(extraction): add audio_ready event emission - Add EventEmitter to emit audio_ready when extraction completes - Pass sessionId and audioPath in event data - Export audioEvents for Main process orchestrator Refs: S3-06 AC1,AC3,AC7 --- services/modules/extraction/ffmpegExtractor.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/services/modules/extraction/ffmpegExtractor.js b/services/modules/extraction/ffmpegExtractor.js index ffec9c0..7939cd5 100644 --- a/services/modules/extraction/ffmpegExtractor.js +++ b/services/modules/extraction/ffmpegExtractor.js @@ -1,3 +1,5 @@ +const EventEmitter = require('events'); +const audioEvents = new EventEmitter(); // Ensure ffmpeg binary is available if (!ffmpegPath) { @@ -75,6 +77,12 @@ module.exports = { progressBar.update(100, { timemark: 'done' }); progressBar.stop(); console.log(`Extraction completed: ${outputAudioPath}`); + + audioEvents.emit('audio_ready', { + sessionId: inputVideoName, + audioPath: outputAudioPath + }); + resolve(); }) .on('error', (err) => { @@ -88,6 +96,6 @@ module.exports = { console.log(); } }); - } - + }, + audioEvents: audioEvents } \ No newline at end of file From 68136594436f10a155a15ed1ac920cea65b98b69 Mon Sep 17 00:00:00 2001 From: Azeufack Noupeu Willy Date: Thu, 20 Nov 2025 14:31:26 +0100 Subject: [PATCH 16/37] feat(main): add pipeline orchestrator for auto-transcription --- electron/main/main.js | 59 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/electron/main/main.js b/electron/main/main.js index 3861ad3..06d5a96 100644 --- a/electron/main/main.js +++ b/electron/main/main.js @@ -2,6 +2,9 @@ import { app, BrowserWindow, ipcMain, dialog } from 'electron'; import { exec } from 'child_process'; import path from 'path'; import { fileURLToPath } from 'url'; +// Import audio events and transcription module +import { audioEvents } from '../../services/modules/extraction/ffmpegExtractor.js'; +import { transcribe } from '../../services/modules/transcription-remote/assembly.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -22,7 +25,61 @@ function createWindow() { mainWindow.loadFile('main/index.html'); } -app.whenReady().then(createWindow); +// Setup pipeline orchestrator +function setupOrchestrator() { + console.log('🎯 [Pipeline] Orchestrator ready. Listening for audio_ready events...'); + + audioEvents.on('audio_ready', async (data) => { + const { audioPath, sessionId } = data; + + console.log(`✅ [Pipeline] Audio ready: ${sessionId}`); + + // AC6: Send status to UI - Audio bereit + mainWindow.webContents.send('pipeline-status', { + sessionId, + status: 'audio_ready', + message: 'Audio bereit' + }); + + try { + // AC4: Status transcription_started + console.log(`🚀 [Pipeline] Starting transcription: ${sessionId}`); + mainWindow.webContents.send('pipeline-status', { + sessionId, + status: 'transcription_started', + message: 'Transkription gestartet' + }); + + // AC2: Auto-start transcription (S2-02b) + await transcribe(audioPath, sessionId); + + // AC6: Status transcription_completed + console.log(`✅ [Pipeline] Transcription completed: ${sessionId}`); + mainWindow.webContents.send('pipeline-status', { + sessionId, + status: 'transcription_completed', + message: 'Transkription abgeschlossen' + }); + + } catch (error) { + // AC5: Error logging + failed_transcription_start + console.error(`❌ [Pipeline] Transcription failed: ${sessionId}`); + console.error(` Error:`, error.message); + + mainWindow.webContents.send('pipeline-status', { + sessionId, + status: 'failed_transcription_start', + message: 'Fehler beim Transkriptionsstart', + error: error.message + }); + } + }); +} + +app.whenReady().then(() => { + createWindow(); + setupOrchestrator(); +}); // Kommunikation vom Renderer (Frontend) ipcMain.handle('convert-video', async (event, filePath) => { From 911cba14fde30476a9b07879bff3a1db9db8bc41 Mon Sep 17 00:00:00 2001 From: Azeufack Noupeu Willy Date: Thu, 20 Nov 2025 14:34:07 +0100 Subject: [PATCH 17/37] chore(typescript): add @ts-ignore for assembly module import --- services/pipeline/jobs/transcribeLatest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/services/pipeline/jobs/transcribeLatest.ts b/services/pipeline/jobs/transcribeLatest.ts index fc75ad5..f632eee 100644 --- a/services/pipeline/jobs/transcribeLatest.ts +++ b/services/pipeline/jobs/transcribeLatest.ts @@ -1,6 +1,7 @@ // services/pipeline/jobs/transcribeLatest.ts import path from 'path'; import fs from 'fs'; +// @ts-ignore: module has no type declarations or cannot be resolved in current TS config import assembly from '../../modules/transcription/assembly'; /** From 925eb33eab45c084e9386ada66d9cb14b966e312 Mon Sep 17 00:00:00 2001 From: Azeufack Noupeu Willy Date: Thu, 20 Nov 2025 15:42:03 +0100 Subject: [PATCH 18/37] chore: add .env.example template for AssemblyAI API key --- .env.example | Bin 0 -> 70 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000000000000000000000000000000000..e12a03aecd9e91b2fb46e4026d59397eef09b281 GIT binary patch literal 70 zcmezW&ygV*2wfR`8Jrk=7$O-Q89W){fn)%f_6EvCGS~vKKSL-(5Ksmp63^fPlnDZ2 IUIs1(0PtrE*8l(j literal 0 HcmV?d00001 From 4ade9575f33fd353522a07abe2f60e2d1be6feb4 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Thu, 20 Nov 2025 16:30:47 +0100 Subject: [PATCH 19/37] Changes to the test --- .../{documentType.txt => documentType.json} | 0 test/integration/gemini/test-gemini.js | 4 +- test/integration/gemini/transcript.json | 122 ++++++++++++++++++ test/integration/gemini/transcript.txt | 53 -------- 4 files changed, 124 insertions(+), 55 deletions(-) rename test/integration/gemini/{documentType.txt => documentType.json} (100%) create mode 100644 test/integration/gemini/transcript.json delete mode 100644 test/integration/gemini/transcript.txt diff --git a/test/integration/gemini/documentType.txt b/test/integration/gemini/documentType.json similarity index 100% rename from test/integration/gemini/documentType.txt rename to test/integration/gemini/documentType.json diff --git a/test/integration/gemini/test-gemini.js b/test/integration/gemini/test-gemini.js index 9df6eb4..7072c43 100644 --- a/test/integration/gemini/test-gemini.js +++ b/test/integration/gemini/test-gemini.js @@ -1,7 +1,7 @@ const gemini = require("../../../services/modules/llm-gemini/gemini.js"); gemini.function({ - inputTranscriptPath: "./transcript.txt", - documentTypePath: "./documentType.txt", + inputTranscriptPath: "./transcript.json", + documentTypePath: "./documentType.json", language: "de" }); \ No newline at end of file diff --git a/test/integration/gemini/transcript.json b/test/integration/gemini/transcript.json new file mode 100644 index 0000000..ca5b9d5 --- /dev/null +++ b/test/integration/gemini/transcript.json @@ -0,0 +1,122 @@ +[ + { + "speaker": "A", + "sentence": "Smoke from hundreds of wildfires in Canada is triggering air quality alerts throughout the US Skylines from Maine to Maryland to Minnesota are gray and smoggy. And in some places, the air quality warnings include the warning to stay inside. We wanted to better understand what's happening here and why, so we called Peter DeCarlo, an associate professor in the Department of Environmental Health and Engineering at Johns Hopkins University. Good morning, Professor.", + "start": 240, + "end": 26560 + }, + { + "speaker": "B", + "sentence": "Good morning.", + "start": 28060, + "end": 28620 + }, + { + "speaker": "A", + "sentence": "So what is it about the conditions right now that have caused this round of wildfires to affect so many people so far away?", + "start": 29100, + "end": 37100 + }, + { + "speaker": "B", + "sentence": "Well, there's a couple of things. The season has been pretty dry already, and then the fact that we're getting hit in the US is because there's a couple weather systems that are essentially channeling the smoke from those Canadian wildfires through Pennsylvania into the mid Atlantic and the Northeast and kind of just dropping the smoke there.", + "start": 39100, + "end": 55820 + }, + { + "speaker": "A", + "sentence": "So what is it in this haze that makes it harmful? And I'm assuming it is harmful.", + "start": 56590, + "end": 60670 + }, + { + "speaker": "B", + "sentence": "It is, it is. The levels outside right now in Baltimore are considered unhealthy. And most of that is due to what's called particulate matter, which are tiny particles, microscopic, smaller than the width of your hair, that can get into your lungs and impact your respiratory system, your cardiovascular system, and even your neurological, your brain.", + "start": 62350, + "end": 82590 + }, + { + "speaker": "A", + "sentence": "What makes this particularly harmful? Is it the volume of particulate? Is it something in particular? What is it exactly? Can you just drill down on that a little bit more?", + "start": 83630, + "end": 92190 + }, + { + "speaker": "B", + "sentence": "Yeah. So the concentration of particulate matter, I was looking at some of the monitors that we have was reaching levels of what are, in science speak, 150 micrograms per meter cubed, which is more than 10 times what the annual average should be in about four times higher than what you're supposed to have on a 24 hour average. And so the concentrations of these particles in the air are just much, much, much higher than we typically see. And exposure to those high levels can lead to a host of health problems.", + "start": 93550, + "end": 123350 + }, + { + "speaker": "A", + "sentence": "And who is most vulnerable? I noticed that in New York City, for example, they're canceling outdoor activities. And so here it is in the early days of summer and they have to keep all the kids inside. So who tends to be vulnerable in a situation like this?", + "start": 123430, + "end": 135990 + }, + { + "speaker": "B", + "sentence": "It's the youngest. So children, obviously, whose bodies are still developing, the elderly who are, you know, their bodies are more in decline and they're more susceptible to the health impacts of breathing, the poor air quality. And then people who have pre existing health conditions, people with respiratory conditions or heart conditions, can be triggered by high levels of air pollution.", + "start": 137610, + "end": 156650 + }, + { + "speaker": "A", + "sentence": "Could this get worse?", + "start": 157450, + "end": 158650 + }, + { + "speaker": "B", + "sentence": "That's a good question. I mean, I think if in some areas it's much worse than others and it just depends on kind of where the smoke is concentrated. I think New York has some of the higher concentrations right now, but that's going to change as that air moves away from the New York area. But over the course of the next few days, we will see different areas being hit at different times with the highest concentrations.", + "start": 162170, + "end": 183420 + }, + { + "speaker": "A", + "sentence": "I was going to ask you about.", + "start": 183740, + "end": 184660 + }, + { + "speaker": "B", + "sentence": "More fires start burning. I don't expect the concentrations to go up too much higher.", + "start": 184660, + "end": 189020 + }, + { + "speaker": "A", + "sentence": "I was going to ask you how and you started to answer this, but how much longer could this last? Forgive me if I'm asking you to speculate, but what do you think?", + "start": 189100, + "end": 196220 + }, + { + "speaker": "B", + "sentence": "Well, I think the fires are going to burn for a little bit longer. But the key for us in the US Is the weather system changing. Right now it's the weather systems that are pulling that air into our Mid Atlantic and Northeast region. As those weather systems change and shift, we'll see that smoke going elsewhere and not impact us in this region as much. I think that's going to be the defining factor. I think the next couple days we're going to see a shift in that weather pattern and start to push the smoke away from where we are.", + "start": 198280, + "end": 227480 + }, + { + "speaker": "A", + "sentence": "And finally, with the impacts of climate change, we are seeing more wildfires. Will we be seeing more of these kinds of wide ranging air quality consequences or circumstances?", + "start": 227930, + "end": 239850 + }, + { + "speaker": "B", + "sentence": "I mean, that is one of the predictions for climate change. Looking into the future, the fire season is starting earlier and lasting longer and we're seeing more frequent fires. So yeah, this is probably something that we'll be seeing more, more frequently. This tends to be much more of an issue in the western U.S. so the eastern U.S. getting hit right now is a little bit new. But yeah, I think with climate change moving forward, this is something that is going to happen more frequently.", + "start": 241370, + "end": 267570 + }, + { + "speaker": "A", + "sentence": "That's Peter DeCarlo, associate professor in the Department of Environmental Health and Engineering at Johns Hopkins University. Professor DeCarlo, thanks so much for joining us and sharing this expertise with us.", + "start": 267970, + "end": 278210 + }, + { + "speaker": "B", + "sentence": "Thank you for having me.", + "start": 279410, + "end": 280530 + } +] \ No newline at end of file diff --git a/test/integration/gemini/transcript.txt b/test/integration/gemini/transcript.txt deleted file mode 100644 index cae9726..0000000 --- a/test/integration/gemini/transcript.txt +++ /dev/null @@ -1,53 +0,0 @@ -Meeting Transcript - Video2Document Project -Date: November 18, 2025 -Attendees: Mike Hughes, Stefan Heyne, Alice Smith, Bob Johnson, Clara Nguyen - -[09:00 AM] Mike Hughes: Good morning, everyone. Let’s start the weekly project meeting for Video2Document. We have multiple points on the agenda today, including updates from each module, integration challenges, and the next sprint plan. - -[09:02 AM] Alice Smith: I’ve been working on the document formatting module. I’ve implemented support for markdown and PDF outputs. Still need to handle custom templates for clients. - -[09:05 AM] Bob Johnson: Video preprocessing is progressing. I’ve added support for multiple video codecs and automated audio extraction. I found that some videos require normalization before sending to the LLM. - -[09:08 AM] Stefan Heyne: For the LLM integration, I tested a few transcripts. Gemini handles summaries well, but we might need to tune prompts to get consistent headings and formatting. - -[09:12 AM] Clara Nguyen: On the storage side, I’ve configured S3 buckets for document storage. Permissions and versioning are set, but we still need to handle large batch uploads efficiently. - -[09:15 AM] Mike Hughes: Great updates. Let’s discuss some issues I noticed in the last integration test. First, audio extraction sometimes fails with videos longer than 20 minutes. Bob, any insights? - -[09:17 AM] Bob Johnson: Yes, I believe the FFmpeg timeout settings need adjustment. Also, some containerized environments lack the right codec libraries, causing failures. - -[09:20 AM] Stefan Heyne: On the LLM side, we noticed that very long transcripts lead to truncated outputs. We may need to split transcripts or chunk content intelligently before sending to Gemini. - -[09:22 AM] Alice Smith: For document formatting, longer outputs sometimes exceed the template limits. We need to implement pagination or splitting by sections. - -[09:25 AM] Clara Nguyen: For batch uploads, we can implement parallel processing with rate limiting to avoid S3 throttling. - -[09:28 AM] Mike Hughes: Action items from today’s discussion: -1. Bob: Adjust FFmpeg settings for long videos and document required codecs. -2. Stefan: Implement transcript chunking and test Gemini output for longer documents. -3. Alice: Add section splitting and pagination to document formatting. -4. Clara: Optimize batch upload process and test with larger datasets. - -[09:32 AM] Bob Johnson: Also, I propose adding logging for all preprocessing steps. This will help debug failed video conversions quickly. - -[09:35 AM] Stefan Heyne: Agreed. Logging in the LLM pipeline will also help identify failed content generations or prompt issues. - -[09:38 AM] Alice Smith: I can integrate logging hooks into the formatting module. Should include timestamped entries and file references. - -[09:40 AM] Clara Nguyen: I’ll add S3 upload logs and alerting for failed uploads. - -[09:42 AM] Mike Hughes: Perfect. Next sprint planning: we’ll prioritize long-video handling, chunked LLM summarization, and document formatting robustness. Everything else can follow in the subsequent sprint. - -[09:45 AM] Bob Johnson: I’ll provide a small script for testing various video lengths. Can be used to benchmark preprocessing times. - -[09:48 AM] Stefan Heyne: I’ll create example transcripts of different sizes to test Gemini LLM’s handling and summarize consistency. - -[09:50 AM] Alice Smith: I’ll create template variations for large documents and test rendering performance. - -[09:52 AM] Clara Nguyen: I’ll simulate batch uploads and stress-test the S3 storage setup. - -[09:55 AM] Mike Hughes: Excellent. Let’s reconvene next Wednesday for progress review. Make sure to push your updates to the repository beforehand. - -[09:57 AM] All: Agreed. - -Meeting adjourned at 10:00 AM. \ No newline at end of file From bf7438b75376d34156579f650583211f53053814 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 12:07:54 +0100 Subject: [PATCH 20/37] cleaned up ffmpegextractor.js --- services/modules/extraction/ffmpegExtractor.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/services/modules/extraction/ffmpegExtractor.js b/services/modules/extraction/ffmpegExtractor.js index 5a31aec..6d00631 100644 --- a/services/modules/extraction/ffmpegExtractor.js +++ b/services/modules/extraction/ffmpegExtractor.js @@ -1,6 +1,3 @@ -const EventEmitter = require('events'); -const audioEvents = new EventEmitter(); - // Ensure ffmpeg binary is available if (!ffmpegPath) { throw new Error('FFmpeg binary not found!'); From c2f22b35252c0c2d5f59926b7113c90ffd17fdfc Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 12:12:46 +0100 Subject: [PATCH 21/37] merged Mikes code for the google gemini module included the requires libraries in the package.json implemented the library into requires.js cleaned up ffmpeg from the events --- .env.example | Bin 70 -> 106 bytes package-lock.json | 693 +++++++++++++++++- package.json | 1 + requires.js | 1 + .../modules/extraction/ffmpegExtractor.js | 3 +- services/modules/llm-gemini/gemini.js | 6 +- 6 files changed, 695 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index e12a03aecd9e91b2fb46e4026d59397eef09b281..68ed7e311439f0b4fd9c10d5cee72eb11cde96d5 100644 GIT binary patch delta 41 scmZ?En&775&fpJ(?hHN*t_<-Ejtl_|o=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.20.1" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -101,6 +184,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -206,7 +298,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -287,6 +378,17 @@ "node": ">=8" } }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -299,6 +401,38 @@ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "engines": { + "node": "*" + } + }, "node_modules/body-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", @@ -325,6 +459,14 @@ "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "optional": true }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -333,6 +475,11 @@ "node": "*" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -428,6 +575,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", @@ -485,6 +648,41 @@ "dev": true, "license": "MIT" }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -618,6 +816,19 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -783,6 +994,11 @@ "url": "https://opencollective.com/express" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -810,6 +1026,28 @@ "pend": "~1.2.0" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/ffmpeg-static": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.2.0.tgz", @@ -855,6 +1093,32 @@ "node": ">=18" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -892,6 +1156,53 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -941,6 +1252,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", @@ -986,6 +1316,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "engines": { + "node": ">=14" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -1026,6 +1381,18 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -1173,6 +1540,28 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -1192,6 +1581,25 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1208,6 +1616,11 @@ "node": ">=8" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -1281,6 +1694,28 @@ "node": ">=4" } }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1295,6 +1730,42 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -1353,6 +1824,11 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", @@ -1366,6 +1842,29 @@ "node": ">= 0.8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -1502,6 +2001,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -1628,6 +2141,25 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -1696,6 +2228,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -1733,6 +2276,20 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1745,6 +2302,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -1845,7 +2414,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1897,6 +2465,14 @@ "node": ">= 0.8" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -1909,11 +2485,124 @@ "which": "bin/which" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index f85f30e..6ac1c4b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "@google/genai": "^1.30.0", "@types/axios": "^0.9.36", "cli-progress": "^3.12.0", "dotenv": "^17.2.3", diff --git a/requires.js b/requires.js index 03c5b7a..e947400 100644 --- a/requires.js +++ b/requires.js @@ -16,3 +16,4 @@ cliProgress = require('cli-progress'); // { app, BrowserWindow, ipcMain, dialog } = require('electron'); electron = require('electron'); +genai = require("@google/genai"); \ No newline at end of file diff --git a/services/modules/extraction/ffmpegExtractor.js b/services/modules/extraction/ffmpegExtractor.js index 6d00631..2f00b15 100644 --- a/services/modules/extraction/ffmpegExtractor.js +++ b/services/modules/extraction/ffmpegExtractor.js @@ -87,6 +87,5 @@ module.exports = { console.log(); } }); - }, - audioEvents: audioEvents + } } \ No newline at end of file diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index d28dda8..7ba043c 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -1,14 +1,10 @@ -const fs = require("fs"); -const path = require("path"); -const { GoogleGenAI } = require("@google/genai"); // Import Google Gemini AI SDK - const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist } -const ai = new GoogleGenAI({ +const ai = new genai.GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" }); From 05449ad8f2807a61679c4228035c6f86ae6ee025 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 12:24:33 +0100 Subject: [PATCH 22/37] removed an empty line --- main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/main.js b/main.js index c0fc7ac..a3bfa9d 100644 --- a/main.js +++ b/main.js @@ -84,7 +84,6 @@ electron.app.whenReady().then(createWindow); electron.ipcMain.on("file_submit", async (event, args) => { try { - let curstep = 0 let totalsteps = 2 + args.document.styles.length From 474e587ff2f1afb2426bd7e3bd9541b00a9d7bbe Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 12:53:05 +0100 Subject: [PATCH 23/37] Added functionality to group modules for frontend --- main.js | 34 ++++++++++++++++++++++++ services/modules/llm-chat_gpt/chatgpt.js | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index a3bfa9d..9967e2a 100644 --- a/main.js +++ b/main.js @@ -82,6 +82,28 @@ electron.app.whenReady().then(createWindow); // mainWindow.webContents.send("fuck", "worked uwu") // }, 5000); +electron.ipcMain.on("get_modules", async (event, args) => { + let module_array = { + "ai_modules":[], + "transcription_modules":[] + } + mapFunctions.forEach(e => { + switch(e.type){ + case "llm": + module_array.ai_modules.push({"name": e.name, "displayname": e.displayname}) + break; + case "transcription": + module_array.transcription_modules.push({"name": e.name, "displayname": e.displayname}) + break; + } + }) + console.log(module_array); + + mainWindow.webContents.send("modules", module_array) +}) + + + electron.ipcMain.on("file_submit", async (event, args) => { try { let curstep = 0 @@ -159,4 +181,16 @@ let q = } ] } +} + + +let q1 = { + "ai_modules": [ + {name:"abc", displayname:"ABC"}, + {name:"qeg", displayname:"aqghegahu"} + ], + "transcription_modules": [ + {name:"abc", displayname:"ABC"}, + {name:"qeg", displayname:"aqghegahu"} + ] } \ No newline at end of file diff --git a/services/modules/llm-chat_gpt/chatgpt.js b/services/modules/llm-chat_gpt/chatgpt.js index 6e9034e..8446af5 100644 --- a/services/modules/llm-chat_gpt/chatgpt.js +++ b/services/modules/llm-chat_gpt/chatgpt.js @@ -1,6 +1,6 @@ module.exports = { name:"chatgpt", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" - type:"document", // value used to differentiate each module to order them in the UI + type:"llm", // value used to differentiate each module to order them in the UI displayname:"ChatGPT", // The displayname used within the UI async function(parameter){ // TODO add code to actually send the transcript to ChatGPT and get a response back From baeb9efd2b0999c783cf7208645f65e892780098 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 13:04:41 +0100 Subject: [PATCH 24/37] fixed file submit code and incorrect property naming in file submission object --- electron/main/preload.js | 4 ++-- electron/main/script.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/electron/main/preload.js b/electron/main/preload.js index 3c6367e..607f438 100644 --- a/electron/main/preload.js +++ b/electron/main/preload.js @@ -4,8 +4,8 @@ try { contextBridge.exposeInMainWorld("explorer", { onFileDrop: (file) => webUtils.getPathForFile(file) }) - contextBridge.exposeInMainWorld("extractor", { - // extract: (file) => {ipcRenderer.send("file_submit", q)} + contextBridge.exposeInMainWorld("submit", { + submit: (meeting_specifications) => {ipcRenderer.send("file_submit", meeting_specifications)} }) contextBridge.exposeInMainWorld("electronAPI", { getFilePath: (file) => {return webUtils.getPathForFile(file)} diff --git a/electron/main/script.js b/electron/main/script.js index f65920d..3f8ba35 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -52,10 +52,10 @@ function checkBoxes() { }, "document": { "module":aiType.value, - "style": selectedStyles + "styles": selectedStyles } }; - ipcRenderer.send("file_submit", sendingPackage) + window.submit.submit(sendingPackage) }else{ alert('The given file is not compatible. These are the available types: [".mp4", ".mov", ".avi", ".mkv"].'); } From b9657e1c9541196fac6d0fcb5b9cfa25ee94342a Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 13:10:07 +0100 Subject: [PATCH 25/37] fixed another typo in the file submission object --- electron/main/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron/main/script.js b/electron/main/script.js index 3f8ba35..6bc5886 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -43,7 +43,7 @@ function checkBoxes() { const aiType = document.getElementById("ai_type"); const sendingPackage = { "video": { - "module":"extraction-video-toaudio", + "module":"extraction-video-to-audio", "inputVideoPath": pathTest, "outputType": outputType.value }, From 31ddddab6abf3d161903daa367bbc0af0e6546f3 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 14:14:16 +0100 Subject: [PATCH 26/37] replaced get modules ipc event handler with a two way handler --- main.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/main.js b/main.js index 9967e2a..8c858c0 100644 --- a/main.js +++ b/main.js @@ -82,7 +82,7 @@ electron.app.whenReady().then(createWindow); // mainWindow.webContents.send("fuck", "worked uwu") // }, 5000); -electron.ipcMain.on("get_modules", async (event, args) => { +ipcMain.handle('get-module-names', async () => { let module_array = { "ai_modules":[], "transcription_modules":[] @@ -97,10 +97,30 @@ electron.ipcMain.on("get_modules", async (event, args) => { break; } }) - console.log(module_array); - - mainWindow.webContents.send("modules", module_array) -}) + // console.log(module_array); + return module_array +}); + + +// electron.ipcMain.on("get_modules", async (event, args) => { +// let module_array = { +// "ai_modules":[], +// "transcription_modules":[] +// } +// mapFunctions.forEach(e => { +// switch(e.type){ +// case "llm": +// module_array.ai_modules.push({"name": e.name, "displayname": e.displayname}) +// break; +// case "transcription": +// module_array.transcription_modules.push({"name": e.name, "displayname": e.displayname}) +// break; +// } +// }) +// console.log(module_array); + +// mainWindow.webContents.send("modules", module_array) +// }) @@ -155,7 +175,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { // }) // } - + } catch (error) { console.log(error); } From eb42a1f3775337148ba69635cca4fa66788431e9 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 14:16:10 +0100 Subject: [PATCH 27/37] fixed small error --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index 8c858c0..0171128 100644 --- a/main.js +++ b/main.js @@ -82,7 +82,7 @@ electron.app.whenReady().then(createWindow); // mainWindow.webContents.send("fuck", "worked uwu") // }, 5000); -ipcMain.handle('get-module-names', async () => { +electron.ipcMain.handle('get-module-names', async () => { let module_array = { "ai_modules":[], "transcription_modules":[] From 465fe8bd41b203200172082cd36a07ad2b4e0317 Mon Sep 17 00:00:00 2001 From: santa Date: Mon, 24 Nov 2025 14:25:29 +0100 Subject: [PATCH 28/37] Summarizer angepasst --- services/modules/jsonTools/transcriptionSummarizer.js | 5 ++++- test/integration/transcriptionSummarizerTest.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index 0003b52..742075b 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -1,4 +1,5 @@ const fs = require("fs"); +const path = require("path"); // Prepare output directory (always storage/transcriptionSummaries under project root) const outputDir = `${__dirname}/../../../storage/transcriptionSummaries`; @@ -6,6 +7,7 @@ if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } + module.exports = { name: "summarize-transcription", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" type: "summarizer", // value used to differentiate each module to order them in the UI @@ -32,7 +34,8 @@ module.exports = { return { error: "Invalid JSON" }; } } - console.log(inputJson); + // console.log(inputJson); + console.log(outputDir); const words = inputJson.words; if (!Array.isArray(words)) { return { error: "No words Array found" }; diff --git a/test/integration/transcriptionSummarizerTest.js b/test/integration/transcriptionSummarizerTest.js index db2564d..22e51f7 100644 --- a/test/integration/transcriptionSummarizerTest.js +++ b/test/integration/transcriptionSummarizerTest.js @@ -6,7 +6,7 @@ const inputJson = JSON.parse(fs.readFileSync("./testFile.json", "utf8")); // Übergabe an den Summarizer transSummarizer.function({ - inputJson: inputJson + json: inputJson }); From 2f5efee9c7f81cadc22f033f9ba20bb5cbc2d66e Mon Sep 17 00:00:00 2001 From: santa Date: Mon, 24 Nov 2025 14:27:49 +0100 Subject: [PATCH 29/37] Summarizer und weiters angepasst --- .../jsonTools/transcriptionSummarizer.js | 4 +- .../jsonTools/transcriptionSummarizer2.js | 121 ++++++++++++++++++ .../modules/transcription-remote/assembly.js | 9 +- services/modules/utility/@startup.js | 7 + test/integration/assemblyTest.js | 18 +++ 5 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 services/modules/jsonTools/transcriptionSummarizer2.js create mode 100644 test/integration/assemblyTest.js diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index 742075b..e6e1318 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -7,6 +7,7 @@ if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } +//Speaker, ALL-Sentences, Start, End module.exports = { name: "summarize-transcription", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" @@ -34,8 +35,7 @@ module.exports = { return { error: "Invalid JSON" }; } } - // console.log(inputJson); - console.log(outputDir); + const words = inputJson.words; if (!Array.isArray(words)) { return { error: "No words Array found" }; diff --git a/services/modules/jsonTools/transcriptionSummarizer2.js b/services/modules/jsonTools/transcriptionSummarizer2.js new file mode 100644 index 0000000..12d00bf --- /dev/null +++ b/services/modules/jsonTools/transcriptionSummarizer2.js @@ -0,0 +1,121 @@ +const fs = require("fs"); +const path = require("path"); + +// Prepare output directory (always storage/transcriptionSummaries under project root) +const outputDir = `${__dirname}/../../../storage/transcriptionSummaries`; +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + +//Speaker, Sentence, Start, End + +module.exports = { + name: "summarize-transcription2", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" + type: "summarizer", // value used to differentiate each module to order them in the UI + displayname: "Summarizer", // The displayname used within the UI + async function(args) { + let inputJson = args.json; + + //JSON Path + if (args.jsonPath) { + try { + const raw = fs.readFileSync(args.jsonPath, "utf-8"); + inputJson = JSON.parse(raw); + } catch (e) { + console.error("Failed to load JSON from file:", e); + return { error: "Could not read JSON from file path." }; + } + } + // JSON parsen + if (typeof inputJson === "string") { + try { + inputJson = JSON.parse(inputJson); + } catch (e) { + console.log("Invalid JSON in summarize-transcription"); + return { error: "Invalid JSON" }; + } + } + + const words = inputJson.words; + if (!Array.isArray(words)) { + return { error: "No words Array found" }; + } + + const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? + const ABBREVIATIONS = new Set(["z.B.", "bzw.", "u.a.", "Dr.", "Mr.", "Mrs.", "Prof.", "etc."]); //TODO weitere Ergaenzen + + const result = []; + let currentSentence = ""; + let currentSpeaker = null; + let startTime = null; + let endTime = null; + + for (const w of words) { + if (!currentSpeaker) currentSpeaker = w.speaker; + if (startTime === null) startTime = w.start; + endTime = w.end; + + //speaker changing + if (currentSpeaker !== w.speaker && currentSentence) { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + currentSentence = ""; + startTime = w.start; + } + currentSpeaker = w.speaker; + currentSentence += (currentSentence ? " " : "") + w.text; //sentence beginning or not + const lastWord = w.text.trim(); + const lastChar = lastWord.slice(-1); + const isAbbreviation = ABBREVIATIONS.has(lastWord); + + //sentence ending + if (ENDINGS.includes(lastChar) && !isAbbreviation) { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + currentSentence = ""; + startTime = null; + endTime = null; + currentSpeaker = null; + } + } + + // safe last sentence + if (currentSentence) { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + } + + + // Output as Text + const output = result.map(r => + `Sprecher ${r.speaker} [${r.start.toFixed(2)} - ${r.end.toFixed(2)}]: ${r.sentence}` + ); + + // Output on cosole + //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); + + try { + const jsonPath = path.join(outputDir, "transcription_result.json"); + fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); + + const txtPath = path.join(outputDir, "transcription_result.txt"); + fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); + + console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); + } catch (err) { + console.error("Error saving Summary:", err); + } + } +} diff --git a/services/modules/transcription-remote/assembly.js b/services/modules/transcription-remote/assembly.js index bf72e1f..d31a67b 100644 --- a/services/modules/transcription-remote/assembly.js +++ b/services/modules/transcription-remote/assembly.js @@ -1,9 +1,6 @@ -//require('dotenv').config(); -//const axios = require('axios'); -//const fs = require('fs'); -const path = require('path'); +require('dotenv').config(); -const API_KEY = process.env.ASSEMBLYAI_API_KEY; +const API_KEY = process.env.API_KEY; const BASE_URL = 'https://api.assemblyai.com/v2'; //---------------------------------------------------Upload audio--------------------------------------------------- @@ -93,7 +90,7 @@ module.exports = { type: 'transcription', displayname: 'AssemblyAI', - run: async (audioFileName) => { + async function(audioFileName) { try { // audioFileName ist nur "datei.mp3" const audioPath = path.join( diff --git a/services/modules/utility/@startup.js b/services/modules/utility/@startup.js index dcf64c8..cfa200e 100644 --- a/services/modules/utility/@startup.js +++ b/services/modules/utility/@startup.js @@ -6,6 +6,13 @@ module.exports = { // We are now calling the example function from the example folder mapFunctions.get("example").function("Startup") + let transcript = await mapFunctions.get("assembly").function('../../storage/audio/IMG_2978.wav'); + + let summary = await mapFunctions.get("summarize-transcription").function({jsonPath:'/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json'}); + + + + // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./a.mp4", outputType:"wav"}) // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./b.mp4", outputType:"wav"}) // mapFunctions.get("extraction-video-to-audio").function({inputVideoPath:"./b.mp4", outputType:"flac"}) diff --git a/test/integration/assemblyTest.js b/test/integration/assemblyTest.js new file mode 100644 index 0000000..76a17ba --- /dev/null +++ b/test/integration/assemblyTest.js @@ -0,0 +1,18 @@ +require('dotenv').config(); +const path = require('path'); +const assemblyModule = require('../../services/modules/transcription-remote/assembly.js'); + +// Audio-Datei oder URL aus Kommandozeile, Standard: test.wav +const audioPath = process.argv[2] || './storage/audio/IMG_2978.wav'; + +(async () => { + try { + const transcript = await assemblyModule.run(audioPath); + + console.log('Transcription succesful'); + console.log('Transcript ID:', transcript?.id); + console.log('Speaker labels:', transcript?.utterances?.length || 0); + } catch (error) { + console.error('Error in Transcription:', error?.message || error); + } +})(); From 812bca8cfbf7555e82d09ba6996cc643f6e9bdb3 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 15:35:32 +0100 Subject: [PATCH 30/37] working on implementing everything Currently getting stuck on the assembly module as assembly ai for some fucking reason blocks me from making any requests This includes making a new user account --- electron/main/index.html | 4 +- main.js | 68 +++++----- package-lock.json | 122 +++++++++++++++++- package.json | 1 + requires.js | 6 +- .../modules/transcription-remote/assembly.js | 10 +- services/modules/utility/@startup.js | 4 +- 7 files changed, 169 insertions(+), 46 deletions(-) diff --git a/electron/main/index.html b/electron/main/index.html index b4bfb5f..6099453 100644 --- a/electron/main/index.html +++ b/electron/main/index.html @@ -21,7 +21,9 @@ diff --git a/main.js b/main.js index 6bb7c72..1c2c0e7 100644 --- a/main.js +++ b/main.js @@ -35,6 +35,8 @@ console.log("------------------------------------------------------------------- + + // --------------------------------------------------------- CLI COMMANDS --------------------------------------------------------- // const rl = readline.createInterface({ @@ -139,7 +141,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { // This code handles the Video to Audio extraction module call await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => { - // console.log(resp); + console.log(resp); audiopath = resp curstep++ mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) @@ -150,42 +152,42 @@ electron.ipcMain.on("file_submit", async (event, args) => { // TODO implement transcription module - // // This code handles the Audio to Text transcription module call - // await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => { - // console.log(resp); - // transcriptpath = resp - // curstep++ - // mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - // }).catch(err => { - // mainWindow.webContents.send("error", err) - // return - // }) + // This code handles the Audio to Text transcription module call + await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => { + console.log(resp); + transcriptpath = resp + curstep++ + mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) + }).catch(err => { + mainWindow.webContents.send("error", err) + return + }) - // // This code summarises the transcript, so that it can be used by an llm - // await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { - // console.log(resp); - // transcriptpath = resp - // curstep++ - // mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - // }).catch(err => { - // mainWindow.webContents.send("error", err) - // return - // }) + // This code summarises the transcript, so that it can be used by an llm + await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { + console.log(resp); + transcriptpath = resp + curstep++ + mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) + }).catch(err => { + mainWindow.webContents.send("error", err) + return + }) // TODO implement documentation module - // // This code handles the Text to Document processing module call - // for (let i = 0; i < args.document.styles.length; i++) { - // await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => { - // console.log(resp); - // transcriptpath = resp - // curstep++ - // mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - // }).catch(err => { - // mainWindow.webContents.send("error", err) - // return - // }) - // } + // This code handles the Text to Document processing module call + for (let i = 0; i < args.document.styles.length; i++) { + await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => { + console.log(resp); + transcriptpath = resp + curstep++ + mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) + }).catch(err => { + mainWindow.webContents.send("error", err) + return + }) + } } catch (error) { diff --git a/package-lock.json b/package-lock.json index 175bfea..76227c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@google/genai": "^1.30.0", "@types/axios": "^0.9.36", + "axios": "^1.13.2", "cli-progress": "^3.12.0", "dotenv": "^17.2.3", "electron": "^39.1.1", @@ -401,6 +402,21 @@ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -591,6 +607,17 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", @@ -767,6 +794,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -795,7 +830,6 @@ "version": "17.2.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", - "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -922,6 +956,20 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -1093,6 +1141,25 @@ "node": ">=18" } }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -1108,6 +1175,40 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -1416,6 +1517,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -1900,6 +2015,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", diff --git a/package.json b/package.json index 6ac1c4b..4b6cc7b 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "@google/genai": "^1.30.0", "@types/axios": "^0.9.36", + "axios": "^1.13.2", "cli-progress": "^3.12.0", "dotenv": "^17.2.3", "electron": "^39.1.1", diff --git a/requires.js b/requires.js index e947400..6036867 100644 --- a/requires.js +++ b/requires.js @@ -16,4 +16,8 @@ cliProgress = require('cli-progress'); // { app, BrowserWindow, ipcMain, dialog } = require('electron'); electron = require('electron'); -genai = require("@google/genai"); \ No newline at end of file +genai = require("@google/genai"); + +axios = require("axios") + +console.log(require('dotenv').config({path: __dirname + '/.env'})); \ No newline at end of file diff --git a/services/modules/transcription-remote/assembly.js b/services/modules/transcription-remote/assembly.js index d31a67b..f2fbe0f 100644 --- a/services/modules/transcription-remote/assembly.js +++ b/services/modules/transcription-remote/assembly.js @@ -1,6 +1,4 @@ -require('dotenv').config(); - -const API_KEY = process.env.API_KEY; +const API_KEY = process.env.ASSEMBLYAI_API_KEY; const BASE_URL = 'https://api.assemblyai.com/v2'; //---------------------------------------------------Upload audio--------------------------------------------------- @@ -93,11 +91,7 @@ module.exports = { async function(audioFileName) { try { // audioFileName ist nur "datei.mp3" - const audioPath = path.join( - __dirname, - '../../../storage/audio', - audioFileName - ); + const audioPath = audioFileName; let audioUrl; diff --git a/services/modules/utility/@startup.js b/services/modules/utility/@startup.js index 2628723..cf6eaf8 100644 --- a/services/modules/utility/@startup.js +++ b/services/modules/utility/@startup.js @@ -6,9 +6,9 @@ module.exports = { // We are now calling the example function from the example folder mapFunctions.get("example").function("Startup") - let transcript = await mapFunctions.get("assembly").function('../../storage/audio/IMG_2978.wav'); + // let transcript = await mapFunctions.get("assembly").function('../../storage/audio/IMG_2978.wav'); - let summary = await mapFunctions.get("summarize-transcription").function({jsonPath:'/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json'}); + // let summary = await mapFunctions.get("summarize-transcription").function({jsonPath:'/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json'}); From af13907fdce7fcc10315b39576a007214fb06f9a Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 16:14:26 +0100 Subject: [PATCH 31/37] added console outputs for debugging --- main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.js b/main.js index 1c2c0e7..c58c261 100644 --- a/main.js +++ b/main.js @@ -139,6 +139,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { let audiopath = "" let transcriptpath = "" + console.log("\n\n Running the Video to Audio Extractor"); // This code handles the Video to Audio extraction module call await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => { console.log(resp); @@ -151,6 +152,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { }) + console.log("\n\n Running the Audio to Transcription module"); // TODO implement transcription module // This code handles the Audio to Text transcription module call await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => { @@ -164,6 +166,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { }) + console.log("\n\n Running the Transcription Summarizer module"); // This code summarises the transcript, so that it can be used by an llm await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { console.log(resp); @@ -175,6 +178,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { return }) + console.log("\n\n Running the LLM module"); // TODO implement documentation module // This code handles the Text to Document processing module call for (let i = 0; i < args.document.styles.length; i++) { From a5a60635fcfffa6931d62899bd6c39c9f2bf56f5 Mon Sep 17 00:00:00 2001 From: santa Date: Mon, 24 Nov 2025 16:40:12 +0100 Subject: [PATCH 32/37] worked on fixing the code --- main.js | 8 +- package-lock.json | 2 + .../jsonTools/transcriptionSummarizer.js | 207 +++++++++--------- .../modules/transcription-remote/assembly.js | 46 ++-- 4 files changed, 140 insertions(+), 123 deletions(-) diff --git a/main.js b/main.js index c58c261..9e7ee55 100644 --- a/main.js +++ b/main.js @@ -139,7 +139,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { let audiopath = "" let transcriptpath = "" - console.log("\n\n Running the Video to Audio Extractor"); + /* console.log("\n\n Running the Video to Audio Extractor"); // This code handles the Video to Audio extraction module call await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => { console.log(resp); @@ -164,11 +164,13 @@ electron.ipcMain.on("file_submit", async (event, args) => { mainWindow.webContents.send("error", err) return }) - +*/ console.log("\n\n Running the Transcription Summarizer module"); // This code summarises the transcript, so that it can be used by an llm - await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { + // await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { + await mapFunctions.get("summarize-transcription").function('/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json').then(resp => { + console.log(resp); transcriptpath = resp curstep++ diff --git a/package-lock.json b/package-lock.json index 76227c9..4de511e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -299,6 +299,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -2534,6 +2535,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index e6e1318..4abaa62 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -1,5 +1,3 @@ -const fs = require("fs"); -const path = require("path"); // Prepare output directory (always storage/transcriptionSummaries under project root) const outputDir = `${__dirname}/../../../storage/transcriptionSummaries`; @@ -14,49 +12,98 @@ module.exports = { type: "summarizer", // value used to differentiate each module to order them in the UI displayname: "Summarizer", // The displayname used within the UI async function(args) { - let inputJson = args.json; + return new Promise(async (resolve, reject) => { + let inputJson = args.json; - //JSON Path - if (args.jsonPath) { - try { - const raw = fs.readFileSync(args.jsonPath, "utf-8"); - inputJson = JSON.parse(raw); - } catch (e) { - console.error("Failed to load JSON from file:", e); - return { error: "Could not read JSON from file path." }; + //JSON Path + if (args.jsonPath) { + try { + const raw = fs.readFileSync(args.jsonPath, "utf-8"); + inputJson = JSON.parse(raw); + } catch (e) { + console.error("Failed to load JSON from file:", e); + return { error: "Could not read JSON from file path." }; + } } - } - // JSON parsen - if (typeof inputJson === "string") { - try { - inputJson = JSON.parse(inputJson); - } catch (e) { - console.log("Invalid JSON in summarize-transcription"); - return { error: "Invalid JSON" }; + // JSON parsen + if (typeof args === "string") { + try { + await fs.readFile(args, 'utf8', function (err, data) { + if (err) throw err; + inputJson = JSON.parse(data); + }); + } catch (e) { + console.log("Invalid JSON in summarize-transcription"); + console.log(e) + return { error: "Invalid JSON" }; + } } - } - const words = inputJson.words; - if (!Array.isArray(words)) { - return { error: "No words Array found" }; - } + const words = inputJson.words; + if (!Array.isArray(words)) { + return { error: "No words Array found" }; + } - const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? - const ABBREVIATIONS = new Set(["z.B.", "bzw.", "u.a.", "Dr.", "Mr.", "Mrs.", "Prof.", "etc."]); //TODO weitere Ergaenzen + const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? + const ABBREVIATIONS = new Set(["z.B.", "bzw.", "u.a.", "Dr.", "Mr.", "Mrs.", "Prof.", "etc."]); //TODO weitere Ergaenzen - const result = []; - let currentSentence = ""; - let currentSpeaker = null; - let startTime = null; - let endTime = null; + const result = []; + let currentSentence = ""; + let currentSpeaker = null; + let startTime = null; + let endTime = null; - for (const w of words) { - if (!currentSpeaker) currentSpeaker = w.speaker; - if (startTime === null) startTime = w.start; - endTime = w.end; - - //speaker changing - if (currentSpeaker !== w.speaker && currentSentence) { + for (const w of words) { + if (!currentSpeaker) currentSpeaker = w.speaker; + if (startTime === null) startTime = w.start; + endTime = w.end; + + //speaker changing + if (currentSpeaker !== w.speaker && currentSentence) { + const lastEntry = result[result.length - 1]; + if (lastEntry && lastEntry.speaker === currentSpeaker) { + lastEntry.sentence += " " + currentSentence; + lastEntry.end = endTime; + } else { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + } + currentSentence = ""; + startTime = w.start; + } + currentSpeaker = w.speaker; + currentSentence += (currentSentence ? " " : "") + w.text; //sentence beginning or not + const lastWord = w.text.trim(); + const lastChar = lastWord.slice(-1); + const isAbbreviation = ABBREVIATIONS.has(lastWord); + + //sentence ending + if (ENDINGS.includes(lastChar) && !isAbbreviation) { + const lastEntry = result[result.length - 1]; + if (lastEntry && lastEntry.speaker === currentSpeaker) { + lastEntry.sentence += " " + currentSentence; + lastEntry.end = endTime; + } else { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + } + currentSentence = ""; + startTime = null; + endTime = null; + currentSpeaker = null; + } + } + + // safe last sentence + if (currentSentence) { const lastEntry = result[result.length - 1]; if (lastEntry && lastEntry.speaker === currentSpeaker) { lastEntry.sentence += " " + currentSentence; @@ -69,70 +116,30 @@ module.exports = { end: endTime }); } - currentSentence = ""; - startTime = w.start; } - currentSpeaker = w.speaker; - currentSentence += (currentSentence ? " " : "") + w.text; //sentence beginning or not - const lastWord = w.text.trim(); - const lastChar = lastWord.slice(-1); - const isAbbreviation = ABBREVIATIONS.has(lastWord); - //sentence ending - if (ENDINGS.includes(lastChar) && !isAbbreviation) { - const lastEntry = result[result.length - 1]; - if (lastEntry && lastEntry.speaker === currentSpeaker) { - lastEntry.sentence += " " + currentSentence; - lastEntry.end = endTime; - } else { - result.push({ - speaker: currentSpeaker, - sentence: currentSentence, - start: startTime, - end: endTime - }); - } - currentSentence = ""; - startTime = null; - endTime = null; - currentSpeaker = null; + // Output as Text + const output = result.map(r => + `Sprecher ${r.speaker} [${r.start.toFixed(2)} - ${r.end.toFixed(2)}]: ${r.sentence}` + ); + + // Output on cosole + //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); + + try { + const jsonPath = path.join(outputDir, "transcription_result.json"); + fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); + + const txtPath = path.join(outputDir, "transcription_result.txt"); + fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); + + console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); + + resolve(jsonPath); + } catch (err) { + console.error("Error saving Summary:", err); + reject(err); } - } - - // safe last sentence - if (currentSentence) { - const lastEntry = result[result.length - 1]; - if (lastEntry && lastEntry.speaker === currentSpeaker) { - lastEntry.sentence += " " + currentSentence; - lastEntry.end = endTime; - } else { - result.push({ - speaker: currentSpeaker, - sentence: currentSentence, - start: startTime, - end: endTime - }); - } - } - - // Output as Text - const output = result.map(r => - `Sprecher ${r.speaker} [${r.start.toFixed(2)} - ${r.end.toFixed(2)}]: ${r.sentence}` - ); - - // Output on cosole - //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); - - try { - const jsonPath = path.join(outputDir, "transcription_result.json"); - fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); - - const txtPath = path.join(outputDir, "transcription_result.txt"); - fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); - - console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); - } catch (err) { - console.error("Error saving Summary:", err); - } + }) } } diff --git a/services/modules/transcription-remote/assembly.js b/services/modules/transcription-remote/assembly.js index f2fbe0f..3b02e4c 100644 --- a/services/modules/transcription-remote/assembly.js +++ b/services/modules/transcription-remote/assembly.js @@ -79,6 +79,8 @@ function saveTranscript(transcript, sessionId) { fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2)); console.log(`Transcript saved: ${outputPath}`); + + return outputPath; } //---------------------------------------------------Modul--------------------------------------------------- @@ -89,29 +91,33 @@ module.exports = { displayname: 'AssemblyAI', async function(audioFileName) { - try { - // audioFileName ist nur "datei.mp3" - const audioPath = audioFileName; + return new Promise(async (resolve, reject) => { + try { + // audioFileName ist nur "datei.mp3" + const audioPath = audioFileName; - let audioUrl; + let audioUrl; - if (/^https?:\/\//i.test(audioFileName)) { - audioUrl = audioFileName; - } else { - if (!fs.existsSync(audioPath)) { - throw new Error(`Audio file not found: ${audioPath}`); + if (/^https?:\/\//i.test(audioFileName)) { + audioUrl = audioFileName; + } else { + if (!fs.existsSync(audioPath)) { + throw new Error(`Audio file not found: ${audioPath}`); + } + audioUrl = await uploadAudio(audioPath); } - audioUrl = await uploadAudio(audioPath); + + const transcriptId = await createTranscript(audioUrl); + const transcript = await pollTranscript(transcriptId); + + const sessionId = getSessionId(audioFileName); + + resolve(saveTranscript(transcript, sessionId)); + + } catch (error) { + console.error('Transcription error:', error.message); + reject(error); } - - const transcriptId = await createTranscript(audioUrl); - const transcript = await pollTranscript(transcriptId); - - const sessionId = getSessionId(audioFileName); - saveTranscript(transcript, sessionId); - - } catch (error) { - console.error('Transcription error:', error.message); - } + }) } }; From 9dfc05e98782465f950604e50eaa4316c183987d Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 16:51:48 +0100 Subject: [PATCH 33/37] Fixed Transcription Summarizer, and now the whole pipeline works (except for LLM, because we need the keys for that) --- main.js | 9 ++++----- services/modules/jsonTools/transcriptionSummarizer.js | 11 +++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/main.js b/main.js index 9e7ee55..83045b1 100644 --- a/main.js +++ b/main.js @@ -139,7 +139,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { let audiopath = "" let transcriptpath = "" - /* console.log("\n\n Running the Video to Audio Extractor"); + console.log("\n\n Running the Video to Audio Extractor"); // This code handles the Video to Audio extraction module call await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: args.video.outputType}).then(resp => { console.log(resp); @@ -164,13 +164,12 @@ electron.ipcMain.on("file_submit", async (event, args) => { mainWindow.webContents.send("error", err) return }) -*/ + console.log("\n\n Running the Transcription Summarizer module"); // This code summarises the transcript, so that it can be used by an llm - // await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { - await mapFunctions.get("summarize-transcription").function('/Users/santa/Proj25/video2document/storage/transcripts/IMG_2978.json').then(resp => { - + // await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => { + await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { console.log(resp); transcriptpath = resp curstep++ diff --git a/services/modules/jsonTools/transcriptionSummarizer.js b/services/modules/jsonTools/transcriptionSummarizer.js index 4abaa62..745c5b7 100644 --- a/services/modules/jsonTools/transcriptionSummarizer.js +++ b/services/modules/jsonTools/transcriptionSummarizer.js @@ -28,10 +28,13 @@ module.exports = { // JSON parsen if (typeof args === "string") { try { - await fs.readFile(args, 'utf8', function (err, data) { - if (err) throw err; - inputJson = JSON.parse(data); - }); + await new Promise((res) => { + fs.readFile(args, 'utf8', function (err, data) { + if (err) throw err; + inputJson = JSON.parse(data); + res() + }); + }) } catch (e) { console.log("Invalid JSON in summarize-transcription"); console.log(e) From 9a0a34981329d442554866ce583f1b7378a6b8da Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 24 Nov 2025 17:01:49 +0100 Subject: [PATCH 34/37] Switched to transcription summarizer2 due to a better output format --- main.js | 2 +- .../jsonTools/transcriptionSummarizer2.js | 185 ++++++++++-------- 2 files changed, 99 insertions(+), 88 deletions(-) diff --git a/main.js b/main.js index 83045b1..39c408d 100644 --- a/main.js +++ b/main.js @@ -169,7 +169,7 @@ electron.ipcMain.on("file_submit", async (event, args) => { console.log("\n\n Running the Transcription Summarizer module"); // This code summarises the transcript, so that it can be used by an llm // await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => { - await mapFunctions.get("summarize-transcription").function(transcriptpath).then(resp => { + await mapFunctions.get("summarize-transcription2").function(transcriptpath).then(resp => { console.log(resp); transcriptpath = resp curstep++ diff --git a/services/modules/jsonTools/transcriptionSummarizer2.js b/services/modules/jsonTools/transcriptionSummarizer2.js index 12d00bf..6993926 100644 --- a/services/modules/jsonTools/transcriptionSummarizer2.js +++ b/services/modules/jsonTools/transcriptionSummarizer2.js @@ -14,108 +14,119 @@ module.exports = { type: "summarizer", // value used to differentiate each module to order them in the UI displayname: "Summarizer", // The displayname used within the UI async function(args) { - let inputJson = args.json; + return new Promise(async (resolve, reject) => { + let inputJson = args.json; - //JSON Path - if (args.jsonPath) { - try { - const raw = fs.readFileSync(args.jsonPath, "utf-8"); - inputJson = JSON.parse(raw); - } catch (e) { - console.error("Failed to load JSON from file:", e); - return { error: "Could not read JSON from file path." }; + //JSON Path + if (args.jsonPath) { + try { + const raw = fs.readFileSync(args.jsonPath, "utf-8"); + inputJson = JSON.parse(raw); + } catch (e) { + console.error("Failed to load JSON from file:", e); + return { error: "Could not read JSON from file path." }; + } } - } - // JSON parsen - if (typeof inputJson === "string") { - try { - inputJson = JSON.parse(inputJson); - } catch (e) { - console.log("Invalid JSON in summarize-transcription"); - return { error: "Invalid JSON" }; + // JSON parsen + if (typeof args === "string") { + try { + await new Promise((res) => { + fs.readFile(args, 'utf8', function (err, data) { + if (err) throw err; + inputJson = JSON.parse(data); + res() + }); + }) + } catch (e) { + console.log("Invalid JSON in summarize-transcription"); + console.log(e) + return { error: "Invalid JSON" }; + } + } + + const words = inputJson.words; + if (!Array.isArray(words)) { + return { error: "No words Array found" }; } - } - const words = inputJson.words; - if (!Array.isArray(words)) { - return { error: "No words Array found" }; - } + const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? + const ABBREVIATIONS = new Set(["z.B.", "bzw.", "u.a.", "Dr.", "Mr.", "Mrs.", "Prof.", "etc."]); //TODO weitere Ergaenzen - const ENDINGS = [".", "!", "?"]; // '...' auch als Satzende ? - const ABBREVIATIONS = new Set(["z.B.", "bzw.", "u.a.", "Dr.", "Mr.", "Mrs.", "Prof.", "etc."]); //TODO weitere Ergaenzen + const result = []; + let currentSentence = ""; + let currentSpeaker = null; + let startTime = null; + let endTime = null; - const result = []; - let currentSentence = ""; - let currentSpeaker = null; - let startTime = null; - let endTime = null; + for (const w of words) { + if (!currentSpeaker) currentSpeaker = w.speaker; + if (startTime === null) startTime = w.start; + endTime = w.end; + + //speaker changing + if (currentSpeaker !== w.speaker && currentSentence) { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + currentSentence = ""; + startTime = w.start; + } + currentSpeaker = w.speaker; + currentSentence += (currentSentence ? " " : "") + w.text; //sentence beginning or not + const lastWord = w.text.trim(); + const lastChar = lastWord.slice(-1); + const isAbbreviation = ABBREVIATIONS.has(lastWord); - for (const w of words) { - if (!currentSpeaker) currentSpeaker = w.speaker; - if (startTime === null) startTime = w.start; - endTime = w.end; - - //speaker changing - if (currentSpeaker !== w.speaker && currentSentence) { + //sentence ending + if (ENDINGS.includes(lastChar) && !isAbbreviation) { + result.push({ + speaker: currentSpeaker, + sentence: currentSentence, + start: startTime, + end: endTime + }); + currentSentence = ""; + startTime = null; + endTime = null; + currentSpeaker = null; + } + } + + // safe last sentence + if (currentSentence) { result.push({ speaker: currentSpeaker, sentence: currentSentence, start: startTime, end: endTime }); - currentSentence = ""; - startTime = w.start; } - currentSpeaker = w.speaker; - currentSentence += (currentSentence ? " " : "") + w.text; //sentence beginning or not - const lastWord = w.text.trim(); - const lastChar = lastWord.slice(-1); - const isAbbreviation = ABBREVIATIONS.has(lastWord); - //sentence ending - if (ENDINGS.includes(lastChar) && !isAbbreviation) { - result.push({ - speaker: currentSpeaker, - sentence: currentSentence, - start: startTime, - end: endTime - }); - currentSentence = ""; - startTime = null; - endTime = null; - currentSpeaker = null; + + // Output as Text + const output = result.map(r => + `Sprecher ${r.speaker} [${r.start.toFixed(2)} - ${r.end.toFixed(2)}]: ${r.sentence}` + ); + + // Output on cosole + //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); + + try { + const jsonPath = path.join(outputDir, "transcription_result.json"); + fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); + + const txtPath = path.join(outputDir, "transcription_result.txt"); + fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); + + console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); + resolve(jsonPath); + } catch (err) { + console.error("Error saving Summary:", err); + reject(err); } - } - - // safe last sentence - if (currentSentence) { - result.push({ - speaker: currentSpeaker, - sentence: currentSentence, - start: startTime, - end: endTime - }); - } - - - // Output as Text - const output = result.map(r => - `Sprecher ${r.speaker} [${r.start.toFixed(2)} - ${r.end.toFixed(2)}]: ${r.sentence}` - ); - - // Output on cosole - //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); - - try { - const jsonPath = path.join(outputDir, "transcription_result.json"); - fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); - - const txtPath = path.join(outputDir, "transcription_result.txt"); - fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); - - console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); - } catch (err) { - console.error("Error saving Summary:", err); - } + }) } } From 9ab98825a2df2c0b9543fd434029e5e9ab3c1458 Mon Sep 17 00:00:00 2001 From: santa Date: Mon, 24 Nov 2025 17:24:08 +0100 Subject: [PATCH 35/37] made it so that the transcript summary file name is not hardcoded anymore --- .../jsonTools/transcriptionSummarizer2.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/services/modules/jsonTools/transcriptionSummarizer2.js b/services/modules/jsonTools/transcriptionSummarizer2.js index 6993926..60d0bb8 100644 --- a/services/modules/jsonTools/transcriptionSummarizer2.js +++ b/services/modules/jsonTools/transcriptionSummarizer2.js @@ -1,5 +1,3 @@ -const fs = require("fs"); -const path = require("path"); // Prepare output directory (always storage/transcriptionSummaries under project root) const outputDir = `${__dirname}/../../../storage/transcriptionSummaries`; @@ -7,6 +5,16 @@ if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } +function getSessionId(inputPath) { + try { + const parsed = new URL(inputPath); + const base = path.basename(parsed.pathname); + return base.replace(/\.[^.]+$/, ''); + } catch { + return path.basename(inputPath, path.extname(inputPath)); + } +} + //Speaker, Sentence, Start, End module.exports = { @@ -115,10 +123,13 @@ module.exports = { //console.log("\n------------\nMerged Transcription Result:\n", output, "\n------------\n"); try { - const jsonPath = path.join(outputDir, "transcription_result.json"); + + let filename = getSessionId(args); + + const jsonPath = path.join(outputDir, `${filename}-${new Date().getTime()}.json`); fs.writeFileSync(jsonPath, JSON.stringify(result, null, 2), "utf-8"); - const txtPath = path.join(outputDir, "transcription_result.txt"); + const txtPath = path.join(outputDir, `${filename}-${new Date().getTime()}.txt`); fs.writeFileSync(txtPath, output.join("\n"), "utf-8"); console.log(`Summary successfully saved:\n- ${jsonPath}\n- ${txtPath}`); From 84cc94aa342123aad253b86e05723fc08cecf735 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Wed, 26 Nov 2025 21:55:19 +0100 Subject: [PATCH 36/37] REST API & Auto Naming --- services/modules/llm-gemini/gemini.js | 45 ++++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/services/modules/llm-gemini/gemini.js b/services/modules/llm-gemini/gemini.js index 7ba043c..6bd88a6 100644 --- a/services/modules/llm-gemini/gemini.js +++ b/services/modules/llm-gemini/gemini.js @@ -4,9 +4,10 @@ if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist } -const ai = new genai.GoogleGenAI({ - apiKey: process.env.GOOGLE_API_KEY // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" -}); +// Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" + +const GEMINI_API_KEY = process.env.GOOGLE_API_KEY; // Ensure Google API key is set in environment variables: export GOOGLE_API_KEY="your_api_key_here" +const GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"; //URL for the REST call, used model and action module.exports = { name: "llm-gemini", @@ -31,19 +32,39 @@ module.exports = { createDocumentFromTranscript: async function(transcriptPath, documentTypePath, language = "en") { // default language is English try { - const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); - const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); + const transcript = await fs.promises.readFile(transcriptPath, "utf-8"); //read transcript file from Path + const documentType = await fs.promises.readFile(documentTypePath, "utf-8"); //read document type from Path + const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; //combine doc type, language and transcript - Change prompt here if needed - const promptText = `${documentType}, in language ${language}, transcript:\n\n${transcript}`; - - const response = await ai.models.generateContent({ - model: "gemini-2.5-flash", // Specify the Gemini model to use - contents: promptText // Input prompt for content generation + // --- REST CALL --- + const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, { //safe model response in variable + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + contents: [ + { + parts: [ + { text: promptText } // Input prompt for content generation + ] + } + ] + }) }); - const output = response.text || ""; // Get generated text from response or default to empty string (if null) + if (!response.ok) { //ok is true when a responce was successfull + const text = await response.text(); + throw new Error(`Gemini API error (${response.status}): ${text}`); + } - const outPath = path.join(outputDir, "test.md"); // Output file path & name TO BE DONE to make dynamic out of input transcript name + const data = await response.json(); + + // Get generated text from response or default to empty string (if null) + const output = data?.candidates?.[0]?.content?.parts?.[0]?.text || ""; + let inputTranscriptName = path.basename(transcriptPath, path.extname(transcriptPath)); // Name for the output file + console.log(inputTranscriptName); + const outPath = path.join(outputDir, `${inputTranscriptName}.md`); // Output file path & name to make naming dynamic. Pulled from input transcript name fs.writeFileSync(outPath, output, "utf8"); // Write output to file console.log("Generated document written to:", outPath); From 0d3535128d6ba35218eddd92b81b71deaaa5b608 Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Sat, 6 Dec 2025 16:43:32 +0100 Subject: [PATCH 37/37] Currently we only have the standard meeting document and the config right now prevents the programm from running. Can be adapted later --- main.js | 4 +++- package-lock.json | 54 ++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/main.js b/main.js index 39c408d..63e4c2b 100644 --- a/main.js +++ b/main.js @@ -183,7 +183,9 @@ electron.ipcMain.on("file_submit", async (event, args) => { // TODO implement documentation module // This code handles the Text to Document processing module call for (let i = 0; i < args.document.styles.length; i++) { - await mapFunctions.get("module-handler").function(args.document.module, {prompt: args.document.styles[i].prompt, transcript: transcriptpath}).then(resp => { + console.log(`\n\n Running the LLM for Document Style ${i+1}`); + + await mapFunctions.get("module-handler").function(args.document.module, {inputTranscriptPath: transcriptpath, documentTypePath: "/Users/mikehughes/PROJ/video2document/storage/documentType/meetingReport.json", language: "en"}).then(resp => { console.log(resp); transcriptpath = resp curstep++ diff --git a/package-lock.json b/package-lock.json index 4de511e..bf45f52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -451,22 +451,27 @@ } }, "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", + "license": "MIT", "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", - "debug": "^4.4.0", + "debug": "^4.4.3", "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/boolean": { @@ -1612,14 +1617,19 @@ } }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/inherits": { @@ -1708,11 +1718,12 @@ } }, "node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", "dependencies": { - "jwa": "^2.0.0", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -2077,21 +2088,6 @@ "node": ">= 0.10" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",