Skip to content

Instantly share code, notes, and snippets.

@trojblue
Created April 9, 2025 18:31
Show Gist options
  • Save trojblue/4a1df5023e6edf91dcda294ce665a390 to your computer and use it in GitHub Desktop.
Save trojblue/4a1df5023e6edf91dcda294ce665a390 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Export Meeting Transcripts
// @namespace https://example.com
// @version 1.0
// @description Extract transcript info (speaker/time/text) from a web page
// @match https://*.larksuite.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// --- Configuration ---
// Adjust these selectors if the page structure changes:
const PARAGRAPH_WRAPPER_SELECTOR = '.subtitle-item-wrapper .paragraph-editor-wrapper';
const SPEAKER_SELECTOR = '.p-user-name';
const TIME_SELECTOR = '.p-time';
const TEXT_SELECTOR = '.mm-paragraph-content .ace-line';
// Create and insert an "Export" button
const exportButton = document.createElement('button');
exportButton.textContent = 'Export Transcripts';
exportButton.style.position = 'fixed';
exportButton.style.top = '10px';
exportButton.style.right = '10px';
exportButton.style.zIndex = '99999';
exportButton.style.padding = '6px 10px';
exportButton.style.backgroundColor = '#007bff';
exportButton.style.color = '#fff';
exportButton.style.border = 'none';
exportButton.style.borderRadius = '4px';
exportButton.style.cursor = 'pointer';
document.body.appendChild(exportButton);
// Download helper
function downloadFile(filename, text) {
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// The main export function
function exportTranscripts() {
const paragraphWrappers = document.querySelectorAll(PARAGRAPH_WRAPPER_SELECTOR);
const results = [];
paragraphWrappers.forEach(wrapper => {
// Extract speaker
const speakerEl = wrapper.querySelector(SPEAKER_SELECTOR);
const speaker = speakerEl ? speakerEl.getAttribute('user-name-content') || speakerEl.textContent.trim() : '';
// Extract time
const timeEl = wrapper.querySelector(TIME_SELECTOR);
const time = timeEl ? timeEl.getAttribute('time-content') || timeEl.textContent.trim() : '';
// Extract raw text from the lines
// Because each transcript can have multiple segments, we gather them all
let textContent = '';
const textEls = wrapper.querySelectorAll(TEXT_SELECTOR);
textEls.forEach(tEl => {
textContent += tEl.innerText.trim() + ' ';
});
textContent = textContent.trim();
// Store the result
results.push({
speaker,
time,
text: textContent
});
});
// Convert to JSON (or CSV, if you prefer)
const jsonString = JSON.stringify(results, null, 2);
// Download the file
downloadFile('transcripts.json', jsonString);
}
// Attach the click handler
exportButton.addEventListener('click', exportTranscripts);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment