Create a file in the src folder with the main plugin code. This file is required.
Refer to the documentation of a third-party service to write this code.
Let's see how the AssemblyAI.ts file is organized in detail:
Define the AssemblyAI class with all the necessary variables and methods:
apiURL - defines the API URL.
apiURL = "";
currentFileId - defines the current file ID.
currentFileId: null | number = null;
apiToken - defines the API token.
apiToken = "";
createAPIUrl - creates the API URL.
createAPIUrl = () => { const api = plugin.getAPI(); this.apiURL = api.origin.replace(/\/+$/, ""); const params = [api.proxy, api.prefix]; if (this.apiURL) { params.forEach((part) => { if (!part) return; const newPart = part.trim().replace(/^\/+/, ""); this.apiURL += newPart ? this.apiURL.length > 0 && this.apiURL[this.apiURL.length - 1] === "/" ? newPart : `/${newPart}` : ""; }); } }
setAPIUrl - sets the API URL.
setAPIUrl = (url: string) => { this.apiURL = url; };
getAPIUrl - retuns the API URL.
getAPIUrl = () => { return this.apiURL; };
setAPIToken - sets the API token.
setAPIToken = (apiToken: string) => { this.apiToken = apiToken; };
getAPIToken - returns the API token.
getAPIToken = () => { return this.apiToken; };
fetchAPIToken - fetches the API token.
fetchAPIToken = async () => { const apiToken = localStorage.getItem("speech-to-text-api-token"); if (!apiToken) return; this.setAPIToken(apiToken); plugin.updateStatus(PluginStatus.active); };
saveAPIToken - saves the API token.
saveAPIToken = (apiToken: string) => { localStorage.setItem("speech-to-text-api-token", apiToken); plugin.updateStatus(!!apiToken ? PluginStatus.active : PluginStatus.hide); };
setCurrentFileId - sets the ID to the current file.
setCurrentFileId = (id: number | null) => { this.currentFileId = id; };
uploadFile - uploads a file which will be transcribed.
uploadFile = async (api_token: string, path: string, data: Blob) => { console.log(`Uploading file: ${path}`); const url = "https://api.assemblyai.com/v2/upload"; try { const response = await fetch(url, { method: "POST", body: data, headers: { "Content-Type": "application/octet-stream", Authorization: api_token, }, }); if (response.status === 200) { const responseData = await response.json(); return responseData["upload_url"]; } else { console.error(`Error: ${response.status} - ${response.statusText}`); return null; } } catch (error) { console.error(`Error: ${error}`); return null; } };
transcribeAudio - transcribes the audio file.
transcribeAudio = async (api_token: string, audio_url: string) => { console.log("Transcribing audio... This might take a moment."); const headers = { authorization: api_token, "content-type": "application/json", }; const response = await fetch("https://api.assemblyai.com/v2/transcript", { method: "POST", body: JSON.stringify({ audio_url }), headers, }); const responseData = await response.json(); const transcriptId = responseData.id; const pollingEndpoint = `https://api.assemblyai.com/v2/transcript/${transcriptId}`; while (true) { const pollingResponse = await fetch(pollingEndpoint, { headers }); const transcriptionResult = await pollingResponse.json(); if (transcriptionResult.status === "completed") { return transcriptionResult; } else if (transcriptionResult.status === "error") { throw new Error(`Transcription failed: ${transcriptionResult.error}`); } else { await new Promise((resolve) => setTimeout(resolve, 3000)); } } };
speechToText - implements the plugin work.
speechToText = async (id: number) => { if (!this.apiToken) return; this.setCurrentFileId(null); if (!this.apiURL) this.createAPIUrl(); const { viewUrl, title, folderId, fileExst } = ( await (await fetch(`${this.apiURL}/files/file/${id}`)).json() ).response; const file = await fetch(viewUrl); const fileBlob = await file.blob(); const upload_url = await this.uploadFile(this.apiToken, viewUrl, fileBlob); const transcript = await this.transcribeAudio(this.apiToken, upload_url); const blob = new Blob([transcript.text], { type: "text/plain;charset=UTF-8", }); const newFile = new File([blob], `blob`, { type: "", lastModified: new Date().getTime(), }); const formData = new FormData(); formData.append("file", newFile); const newTitle = `${title.replaceAll(fileExst, "")} text`; try { const sessionRes = await fetch( `${this.apiURL}/files/${folderId}/upload/create_session`, { method: "POST", headers: { "Content-Type": "application/json;charset=utf-8", }, body: JSON.stringify({ createOn: new Date(), fileName: `${newTitle}.txt`, fileSize: newFile.size, relativePath: "", }), } ); const sessionData = (await sessionRes.json()).response.data; const data = await fetch(`${sessionData.location}`, { method: "POST", body: formData, }); const { id: fileId } = (await data.json()).data; return fileId; } catch (e) { console.log(e); } return { actions: [Actions.showToast], toastProps: [{ type: ToastType.success, title: "" }], } as IMessage; };
Declare the AssemblyAI class instance:
const assemblyAI = new AssemblyAI();
Export the created plugin instance:
export default assemblyAI;