From 4e396aa9a3a9f666104400c672ae6b4c346e374d Mon Sep 17 00:00:00 2001 From: Active Inference Institute <79860900+ActiveInferenceInstitute@users.noreply.github.com> Date: Mon, 27 Feb 2023 13:42:28 -0800 Subject: [PATCH] Files from Dave --- Archive/StanzaNLP.py | 306 ++++++++ Archive/StanzaNLP_parse-only.py | 176 +++++ Archive/SubmitToCloudWhisper_textbook.py | 808 ++++++++++++++++++++ Archive/sentencesToTranscripts.py | 889 ++++++++++++++++++++++ Archive/sentencesToTranscripts_X.py | 895 +++++++++++++++++++++++ 5 files changed, 3074 insertions(+) create mode 100644 Archive/StanzaNLP.py create mode 100644 Archive/StanzaNLP_parse-only.py create mode 100644 Archive/SubmitToCloudWhisper_textbook.py create mode 100644 Archive/sentencesToTranscripts.py create mode 100644 Archive/sentencesToTranscripts_X.py diff --git a/Archive/StanzaNLP.py b/Archive/StanzaNLP.py new file mode 100644 index 0000000..2875ef4 --- /dev/null +++ b/Archive/StanzaNLP.py @@ -0,0 +1,306 @@ +# +# cd "/mnt/d/Documents/FEP-AI/Friston, Karl J (b-1959)/2021-06-21 ActInfLab - Karl Friston - Symposium for Participants\Stanford Core Friston Symposium" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP.py" "FSym2021-1" +# cd /mnt/e/Documents/DiscourseAnalysis/podcast_Mindscape/2022/09/19 +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP.py" "ms211" "ms211_211-solo einsteins equation.mp3.sentences.csv_transcript.txt" +# cd "/mnt/d/Documents/FEP-AI/2023 GuestStream/gs035-1" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP.py" "gs035-1" "gs035-1_ActInf GuestStream 035.1 ~ Jordan Hall & Matthew Pirkowski.m4a.sentences.csv_transcript.txt" | tee gs035-1.m4a_stanza.json & +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP.py" "gs035-1" "ActInf GuestStream 035.1 ~ Jordan Hall & Matthew Pirkowski.txt" +# python3 - "gs035-1" "ActInf GuestStream 035.1 ~ Jordan Hall & Matthew Pirkowski.txt" +# https://github.com/stanfordnlp/stanza/ + +import stanza +import requests +import time +import re +import sys +import math +import csv +import json + +if __name__ == "__main__": + print(f"Arguments count: {len(sys.argv)}") + if len(sys.argv) == 1: + print("StanzaNLP. Needs parameters docLabel (key binding references to this doc),") + print(" inSentFile (incoming text transcript file *.m4a.sentences.csv_transcript.txt; - would pipe this in as stdin.)") + print("Optional params outDir (defaults to working directory '.').") + print("Created at outDir: *_stanza_ner.csv (per-sentence), *_stanza_nerSumm.csv (consolidated across doc), *_stanza_Parse.csv ") + quit() + elif len(sys.argv) < 3: + print("Need at least docLabel, inSentFile; optional outDir. Exiting!") + quit() + # +# +docLabel = sys.argv[1] +inSentFile = sys.argv[2] +print("docLabel, inSentFile " + "'" + docLabel + "', '" + inSentFile + "'") + +if len(sys.argv) > 3: + outDir = sys.argv[3] +else: + outDir = "." #publish to working directory! + +print("outDir: " + "'" + outDir + "'") + +proxies = {'http': 'http://ip:port', 'https': 'http://ip:port'} +#stanza.download('en', proxies=proxies) # This downloads the English models for the neural pipeline +stanza.download('en') # This downloads the English models for the neural pipeline +# Following sets up a default neural pipeline in English +nlp = stanza.Pipeline('en') +#nlp = stanza.Pipeline('en', processors='tokenize,ner', package={"ner": ["ncbi_disease", "ontonotes"]}) +#nlp = stanza.Pipeline('en', processors='tokenize,ner', package={"ner": ["ncbi_disease", "ontonotes"], 'coref': [], 'coref.algorithm' : 'neural'}) +#nlpX = stanza.Pipeline('en', processors='tokenize,ner', package={"ner": ["ncbi_disease", "ontonotes"], 'coref': [], 'coref.algorithm' : 'neural'}) +s1="All right, hello everyone. Welcome. This is ActInf livestream number 51 one. We are in the second discussion of this paper, canonical Neural Networks perform Active Inference. Welcome to the active inference institute. We're a participatory online institute that is communication, learning and practicing applied active inference. You can find us on this slide and this is recorded in an archived livestream. So please provide us feedback so we can improve our work. All backgrounds and perspectives are welcome and we'll follow good video etiquette for live streams, head over active inference.org to learn more about the institute and how to participate in projects and learning groups. All right, we're in ActInf livestream number 51 one, and having our first nonsolo discussion on this paper, canonical Neural Networks perform active inference and really appreciative that you've joined today. It's going to be a great discussion. We'll begin with introductions. I'll say hello and then please just jump in however you'd like. And we can start by setting some context. So I'm Daniel, I'm a researcher in California, and I was interested in this paper because we've been talking a lot about active inference from a variety of different perspectives, from the more fundamental math and physics to some applications, philosophy, embodiment, all these really interesting threads. And this paper seems to make a really clear meaningful contribution and connection by connecting active inference entities and this approach of modeling to neural networks which are in daily use globally. So thought it was a fascinating connection and really appreciate that we can talk about this today. So to you and welcome. Go forward, Takuya, however you'd like to introduce and say hello. Yeah. Hi. I'm Takuya Isomura, neuroscientist in Lique Brain Science Institute in Japan. I'm particularly interested in universal characterization of neural network and brain using mathematical techniques. So this work I believe important as a link between active brain forest aspect, Bayesian aspect of the brain, and the dynamics system aspect of the neural network. So I'm very happy to join this discussion session. Thank you for invitation. Nice to meet you." +s1="Because there might be settings where that is strictly effective and the simplest rule whereas there's other settings where that's going to be tragic. So in the special case where the entire environment is observable without errors like a chess game, then there's an equivalence between correlation of risk or loss on observables or on hidden states. But also I'm sure there's ways to construct them that are overfit. Worst case, there's some computational complexity, trade offs, but the problem becomes fully stateable. There's a parallelism or a concordance being drawn between the loss function of Neural networks and the variational free energy of the parameterized model there." +s1="If a catalog is an instance of set menu and an agent offers items for sale in the catalog and a kind of entity is in the catalog and a kind of entity is a subclass of prepared food and a physical is an instance of a class and another physical is an instance of the kind of entity and the physical is not equal to the other physical and the physical is price a currency measure for the agent1 and the other physical is price another currency measure for the agent2, then the currency measure is equal to the other currency measure" +s1="Mr. Phelps, the man over there, bought these toys for his children. They're very happy now!" +#print(*[f'word: {word.text}\tupos: {word.upos}\txpos: {word.xpos}\tfeats: {word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') +#print(*[f'id: {word.id}\tword: {word.text}\tupos: {word.upos}\txpos: {word.xpos}\tfeats: {word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') +#print(*[f'id: {word.id}\tword: {word.text}\tupos: {word.upos}\txpos: {word.xpos}\thead id: {word.head}\thead: {sent.words[word.head-1].text if word.head > 0 else "root"}\tfeats: {word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') +#print('id\tword\tUPoS\tXPoS\theadId\thead\tfeats') +#print(*[f'{word.id}\t{word.text}\t{word.upos}\t{word.xpos}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "root"}\t{word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') + +#print(*[f'id: {word.id}\tword: {word.text}\thead id: {word.head}\thead: {sent.words[word.head-1].text if word.head > 0 else "root"}\tdeprel: {word.deprel}' for sent in doc.sentences for word in sent.words], sep='\n') + +s1="My sister is married to Mwaga and has two children. Barack Obama was born in Hawaii. Barack Obama was elected in 2008. He is the president. I flew to Mwaga, Indonesia, last year. Obama was elected in 2008." +# 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +# 0 1 2 3 4 5 6 7 8 +#doc = nlp(s1) +s1="3-D. 3-hitter. 3rd October Organization. a capella singing. a cappella singing. a la carte. A-bomb. A-horizon. A-line. A-list. A-team. A. A. Michelson. A. A. Milne. able-bodiedism. able-bodism. ABO blood group system. Abruzzi e Molise. absence without leave. Abu Ali al-Husain ibn Abdallah ibn Sina. Abu Hafs al-Masri Brigades. Abu Nidal Organization. Abul-Walid Mohammed ibn-Ahmad Ibn-Mohammed ibn-Roshd. Aby Moritz Warburg. Acadia National Park. Acapulco de Juarez. accessory after the fact. accessory cephalic vein. accessory during the fact. accessory hemiazygos vein. accessory hemiazygous vein. accessory vertebral vein. accommodating lens implant. accord and satisfaction. accordance of rights. ace of clubs." +doc = nlp(s1) + + +# -------- sentences CSV + +inSentPath = inSentFile + +sent_file = open(inSentPath, "r", newline=None) +if (sent_file == None): + print(inSentPath + " not found") +else: + #allSents = sent_file.readlines() + allSents = sent_file.read() + + +doc = nlp(allSents) +#NER +#for ent in doc.ents: +# print(ent) + +# stanza_nerSumm.csv (consolidated across doc!) + +""" #might want to do case folding based on Type! +Fold case +DATE +N if contains a month-name, else Y +#monthList = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec','january','february','march','april','june','july','august','september','october','november','december'] +monthRegex = re.compile(r'jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec') +Fold case = N: +noFoldList = ['EVENT', 'GPE', 'LOC', 'NORP', 'ORG', 'PERSON', 'PRODUCT', 'WORK_OF_ART'] + +Fold case = Y: +CARDINAL +ORDINAL +PERCENT +TIME +all other? +""" +monthRegex = re.compile(r'jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec') +noFoldList = ['EVENT','FAC','GPE','LOC','NORP','ORG','PERSON','PRODUCT','WORK_OF_ART'] + +nerDict = {} +for ent in doc.ents: + entText = ent.text + entType = ent.type + if entType in noFoldList: + pass + elif entType == 'DATE': + #if entText.lower() in monthList: + if monthRegex.search(entText.lower()): + pass + else: + entText = entText.lower() + # + else: + entText = entText.lower() + # + if entText in nerDict: + if entType in nerDict[entText]: + nerDict[entText][entType] += 1 + else: + #nerDict[entText][entType] = 1 + #nerDict[entText] = {entType: 1} + nerDict[entText].update({entType: 1}) + # + else: + nerDict[entText] = {entType: 1} + # +# + +#print(nerDict) +print('NerEntity\ttype\tcount') +nerKeys=nerDict.keys() +for ner in nerKeys: + nerTypes = nerDict[ner] + nerTypeKeys = nerTypes.keys() + for nerType in nerTypeKeys: + print(ner + "\t" + nerType + "\t" + str(nerDict[ner][nerType])) + + +#print(*[f'entity: {ent.text}\ttype: {ent.type}' for ent in doc.ents], sep='\n') + +#print(*[f'entity: {ent.text}\ttype: {ent.type}\tstart_chars{ent.start_char}\tend_char{ent.end_char}' for sent in doc.sentences for ent in sent.ents], sep='\n') + +# stanza_ner.csv (per sentence with NERs) +print('sent\tentity\ttype\tstart_char\tend_char') +for sentId, sent in enumerate(doc.sentences): + for ent in sent.ents: + print(*[f'{1+sentId}\t{ent.text}\t{ent.type}\t{ent.start_char}\t{ent.end_char}'], sep='\n') + +stanzaParsePath = outDir + +if stanzaParsePath[-1] != "/": + stanzaParsePath += "/" + +# Created at outDir: *_stanza_ner.csv (per-sentence), *_stanza_nerSumm.csv (consolidated across doc), *_stanza_Parse.csv +stanzaParsePath += docLabel + "_" + inSentFile + "_stanza_Parse.csv" + +print("to write-open stanzaParsePath:") +print(stanzaParsePath) + +sPubF = open(stanzaParsePath, "w") + +# *_stanza_Parse.csv combined dependency and constituent parses across doc +print('sent\tid\tword\tlemma\tUPoS\tXPoS\tstartChar\tendChar\theadId\thead\tdepRel\tfeats') +sPubF.write('sent\tid\tword\tlemma\tUPoS\tXPoS\tstartChar\tendChar\theadId\thead\tdepRel\tfeats') +sPubF.write("\r\n") + +for sentId, sent in enumerate(doc.sentences): + print(*[f'{1+sentId}\t{word.id}\t{word.text}\t{word.lemma}\t{word.upos}\t{word.xpos}\t{word.start_char}\t{word.end_char}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "(root)"}\t{word.deprel}\t{word.feats if word.feats else "_"}' for word in sent.words], sep='\n') + for word in sent.words: + #if len(word.text) > 0: + sPubOut = str(1+sentId) + "\t" + sPubOut += str(word.id) if word.id > 0 else "" + sPubOut += "\t" + ( str(word.text) if word.text.isnumeric() else word.text ) + "\t" + ( str(word.lemma) if word.lemma.isnumeric() else word.lemma) + "\t" + ( str(word.upos) if word.upos.isnumeric() else word.upos ) + "\t" + ( str(word.xpos) if word.xpos.isnumeric() else word.xpos ) + "\t" + sPubOut += str(word.start_char) if word.start_char >= 0 else "" + sPubOut += "\t" + sPubOut += str(word.end_char) if word.end_char >= 0 else "" + sPubOut += "\t" + sPubOut += str(word.head) if word.head >= 0 else "" + sPubOut += "\t" + if word.head >= 0: + sPubOut += sent.words[word.head-1].text if word.head > 0 else "(root)" + # + sPubOut += "\t" + word.deprel + "\t" + sPubOut += word.feats if word.feats else "_" + #sPubF.write(str(1+sentId) + "\t" + str(word.id) + "\t" + word.text + "\t" + word.lemma + "\t" + word.upos + "\t" + word.xpos + "\t" + str(word.start_char) + "\t" + str(word.end_char) + "\t" + str(word.head) + "\t" + sent.words[word.head-1].text if word.head > 0 else "(root)" + "\t" + word.deprel + "\t" + word.feats if word.feats else "_") + sPubF.write(sPubOut) + sPubF.write("\r\n") + # + # +# + +""" +2023-02-03 21:19:34 INFO: Loading these models for language: en (English): +============================ +| Processor | Package | +---------------------------- +| tokenize | combined | +| pos | combined | +| lemma | combined | +| depparse | combined | +| sentiment | sstplus | +| constituency | wsj | +| ner | ontonotes | +============================ + +2023-02-03 21:19:34 INFO: Use device: cpu +2023-02-03 21:19:34 INFO: Loading: tokenize +2023-02-03 21:19:34 INFO: Loading: pos +2023-02-03 21:19:35 INFO: Loading: lemma +2023-02-03 21:19:35 INFO: Loading: depparse +2023-02-03 21:19:35 INFO: Loading: sentiment +2023-02-03 21:19:35 INFO: Loading: constituency +2023-02-03 21:19:36 INFO: Loading: ner +2023-02-03 21:19:36 INFO: Done loading processors! +""" + +sPubF.close() + +# Ignore following examples +""" +s4='It was raining where Daniel arrived in Brazil. When he came from Brazil, Daniel was fortified with letters from Conan but otherwise did not know a soul except Herbert. Yet this giant man from the Northeast, who had never worn an overcoat or experienced a change of seasons, did not seem surprised by his past.' +s4='It was raining where Daniel landed in Brazil.' + +#with stanza.Pipeline(annotators=['tokenize','ssplit','pos','lemma','ner','parse','depparse','coref'], +# +# properties={'annotators': 'coref', 'coref.algorithm' : 'neural'},timeout=30000, memory='16G') as client: +# aa="h" + + +doc4 = nlp(s4) + +#print('sent\tentity\ttype') +#for sentId, sent in enumerate(doc4.sentences): +# print(*[f'{1+sentId}\t{ent.text}\t{ent.type}' for ent in sent.ents], sep='\n') + + +#print(*[f'entity: {ent.text}\ttype: {ent.type}' for ent in doc4.ents], sep='\n') + +# stanza_nerSumm.csv (consolidate across doc!) +nerDict = {} +for ent in doc4.ents: + entText = ent.text + entType = ent.type + if entText in nerDict: + if entType in nerDict[entText]: + nerDict[entText][entType] += 1 + else: + #nerDict[entText][entType] = 1 + #nerDict[entText] = {entType: 1} + nerDict[entText].update({entType: 1}) + # + else: + nerDict[entText] = {entType: 1} + # +# + +#print(nerDict) + +# stanza_ner.csv (per sentence with NERs) +print('sent\tentity\ttype\tstart_char\tend_char') +for sentId, sent in enumerate(doc4.sentences): + for ent in sent.ents: + print(*[f'{1+sentId}\t{ent.text}\t{ent.type}\t{ent.start_char}\t{ent.end_char}'], sep='\n') + + + +# *_stanza_Parse.csv combined dependency and constituent parses across doc +print('sent\tid\tword\tlemma\tUPoS\tXPoS\tstartChar\tendChar\theadId\thead\tdepRel\tfeats') + +for sentId, sent in enumerate(doc4.sentences): + print(*[f'{1+sentId}\t{word.id}\t{word.text}\t{word.lemma}\t{word.upos}\t{word.xpos}\t{word.start_char}\t{word.end_char}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "(root)"}\t{word.deprel}\t{word.feats if word.feats else "_"}' for word in sent.words], sep='\n') + #print(*[f'{1+sentId}\t{word.id}\t{word.text}\t{word.lemma}\t{word.upos}\t{word.xpos}\t{word.start_char}\t{word.end_char}\t{word.head}\t\t{word.deprel}\t{word.feats if word.feats else "_"}' for word in sent.words], sep='\n') + + +#for index_chain,chain in enumerate(chains): +# chain_dict[index_chain]={} +# chain_dict[index_chain]['ref']='' + + + +#print('sent\tid\tword\theadId\thead\tdepRel') +#for sentId, sent in enumerate(doc.sentences): +# print(*[f'{1+sentId}\t{word.id}\t{word.text}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "root"}\t{word.deprel}' for sent in doc.sentences for word in sent.words], sep='\n') +# + + +#doc.sentences[0].print_dependencies() + +s2="It strikes me then that it would be useful to link that operational ontology to the underlying maths." +doc2 = nlp(s2) +print('id\tword\tUPoS\tXPoS\thead Id\thead\tfeats') +print(*[f'{word.id}\t{word.text}\t{word.upos}\t{word.xpos}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "root"}\t{word.feats if word.feats else "_"}' for sent in doc2.sentences for word in sent.words], sep='\n') +print('id\tword\tUPoS\tXPoS\thead Id\thead\tfeats') +print(*[f'{word.id}\t{word.text}\t{word.upos}\t{word.xpos}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "root"}\t{word.feats if word.feats else "_"}' for sent in doc2.sentences for word in sent.words], sep='\n') + """ \ No newline at end of file diff --git a/Archive/StanzaNLP_parse-only.py b/Archive/StanzaNLP_parse-only.py new file mode 100644 index 0000000..b82c3f4 --- /dev/null +++ b/Archive/StanzaNLP_parse-only.py @@ -0,0 +1,176 @@ +# +# cd /mnt/e/Documents/DiscourseAnalysis/podcast_Mindscape/2022/09/19 +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP_parse-only.py" "ms211" "ms211_211-solo einsteins equation.mp3.sentences.csv_transcript.txt" +# cd "/mnt/d/Documents/FEP-AI/2023 GuestStream/gs035-1" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP_parse-only.py" "gs035-1" "gs035-1_ActInf GuestStream 035.1 ~ Jordan Hall & Matthew Pirkowski.m4a.sentences.csv_transcript.txt" | tee gs035-1.m4a_stanza.json & +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/StanzaNLP_parse-only.py" "gs035-1" "ActInf GuestStream 035.1 ~ Jordan Hall & Matthew Pirkowski.txt" +# python3 - "gs035-1" "ActInf GuestStream 035.1 ~ Jordan Hall & Matthew Pirkowski.txt" +# https://github.com/stanfordnlp/stanza/ + +import stanza +import requests +import time +import re +import sys +import math +import csv +import json + +if __name__ == "__main__": + print(f"Arguments count: {len(sys.argv)}") + if len(sys.argv) == 1: + print("StanzaNLP. Needs parameters docLabel (key binding references to this doc),") + print(" inSentFile (incoming text transcript file *.m4a.sentences.csv_transcript.txt; - would pipe this in as stdin.)") + print("Optional params outDir (defaults to working directory '.').") + print("Created at outDir: *_stanza_ner.csv (per-sentence), *_stanza_nerSumm.csv (consolidated across doc), *_stanza_Parse.csv ") + quit() + elif len(sys.argv) < 3: + print("Need at least docLabel, inSentFile; optional outDir. Exiting!") + quit() + # +# +docLabel = sys.argv[1] +inSentFile = sys.argv[2] +print("docLabel, inSentFile " + "'" + docLabel + "', '" + inSentFile + "'") + +if len(sys.argv) > 3: + outDir = sys.argv[3] +else: + outDir = "." #publish to working directory! + +print("outDir: " + "'" + outDir + "'") + +proxies = {'http': 'http://ip:port', 'https': 'http://ip:port'} +#stanza.download('en', proxies=proxies) # This downloads the English models for the neural pipeline +stanza.download('en') # This downloads the English models for the neural pipeline + +# Following sets up a default neural pipeline in English +nlp = stanza.Pipeline('en') + +#nlp = stanza.Pipeline('en', processors='tokenize,ner', package={"ner": ["ncbi_disease", "ontonotes"]}) +#nlp = stanza.Pipeline('en', processors='tokenize,ner', package={"ner": ["ncbi_disease", "ontonotes"], 'coref': [], 'coref.algorithm' : 'neural'}) +#nlpX = stanza.Pipeline('en', processors='tokenize,ner', package={"ner": ["ncbi_disease", "ontonotes"], 'coref': [], 'coref.algorithm' : 'neural'}) +s1="All right, hello everyone. Welcome. This is ActInf livestream number 51 one. We are in the second discussion of this paper, canonical Neural Networks perform Active Inference. Welcome to the active inference institute. We're a participatory online institute that is communication, learning and practicing applied active inference. You can find us on this slide and this is recorded in an archived livestream. So please provide us feedback so we can improve our work. All backgrounds and perspectives are welcome and we'll follow good video etiquette for live streams, head over active inference.org to learn more about the institute and how to participate in projects and learning groups. All right, we're in ActInf livestream number 51 one, and having our first nonsolo discussion on this paper, canonical Neural Networks perform active inference and really appreciative that you've joined today. It's going to be a great discussion. We'll begin with introductions. I'll say hello and then please just jump in however you'd like. And we can start by setting some context. So I'm Daniel, I'm a researcher in California, and I was interested in this paper because we've been talking a lot about active inference from a variety of different perspectives, from the more fundamental math and physics to some applications, philosophy, embodiment, all these really interesting threads. And this paper seems to make a really clear meaningful contribution and connection by connecting active inference entities and this approach of modeling to neural networks which are in daily use globally. So thought it was a fascinating connection and really appreciate that we can talk about this today. So to you and welcome. Go forward, Takuya, however you'd like to introduce and say hello. Yeah. Hi. I'm Takuya Isomura, neuroscientist in Lique Brain Science Institute in Japan. I'm particularly interested in universal characterization of neural network and brain using mathematical techniques. So this work I believe important as a link between active brain forest aspect, Bayesian aspect of the brain, and the dynamics system aspect of the neural network. So I'm very happy to join this discussion session. Thank you for invitation. Nice to meet you." +s1="Because there might be settings where that is strictly effective and the simplest rule whereas there's other settings where that's going to be tragic. So in the special case where the entire environment is observable without errors like a chess game, then there's an equivalence between correlation of risk or loss on observables or on hidden states. But also I'm sure there's ways to construct them that are overfit. Worst case, there's some computational complexity, trade offs, but the problem becomes fully stateable. There's a parallelism or a concordance being drawn between the loss function of Neural networks and the variational free energy of the parameterized model there." +s1="If a catalog is an instance of set menu and an agent offers items for sale in the catalog and a kind of entity is in the catalog and a kind of entity is a subclass of prepared food and a physical is an instance of a class and another physical is an instance of the kind of entity and the physical is not equal to the other physical and the physical is price a currency measure for the agent1 and the other physical is price another currency measure for the agent2, then the currency measure is equal to the other currency measure" +s1="Mr. Phelps, the man over there, bought these toys for his children. They're very happy now!" +#print(*[f'word: {word.text}\tupos: {word.upos}\txpos: {word.xpos}\tfeats: {word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') +#print(*[f'id: {word.id}\tword: {word.text}\tupos: {word.upos}\txpos: {word.xpos}\tfeats: {word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') +#print(*[f'id: {word.id}\tword: {word.text}\tupos: {word.upos}\txpos: {word.xpos}\thead id: {word.head}\thead: {sent.words[word.head-1].text if word.head > 0 else "root"}\tfeats: {word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') +#print('id\tword\tUPoS\tXPoS\theadId\thead\tfeats') +#print(*[f'{word.id}\t{word.text}\t{word.upos}\t{word.xpos}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "root"}\t{word.feats if word.feats else "_"}' for sent in doc.sentences for word in sent.words], sep='\n') + +#print(*[f'id: {word.id}\tword: {word.text}\thead id: {word.head}\thead: {sent.words[word.head-1].text if word.head > 0 else "root"}\tdeprel: {word.deprel}' for sent in doc.sentences for word in sent.words], sep='\n') + +s1="My sister is married to Mwaga and has two children. Barack Obama was born in Hawaii. Barack Obama was elected in 2008. He is the president. I flew to Mwaga, Indonesia, last year. Obama was elected in 2008." +# 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +# 0 1 2 3 4 5 6 7 8 +#doc = nlp(s1) + +# -------- sentences CSV + +inSentPath = inSentFile + +sent_file = open(inSentPath, "r", newline=None) +if (sent_file == None): + print(inSentPath + " not found") +else: + #allSents = sent_file.readlines() + allSents = sent_file.read() + + +doc = nlp(allSents) + +stanzaParsePath = outDir + +if stanzaParsePath[-1] != "/": + stanzaParsePath += "/" + +# Created at outDir: *_stanza_ner.csv (per-sentence), *_stanza_nerSumm.csv (consolidated across doc), *_stanza_Parse.csv +stanzaParsePath += docLabel + "_" + inSentFile + "_stanza_Parse.csv" + +print("to write-open stanzaParsePath:") +print(stanzaParsePath) + +sPubF = open(stanzaParsePath, "w") + +# *_stanza_Parse.csv combined dependency and constituent parses across doc +print('sent\tid\tword\tlemma\tUPoS\tXPoS\tstartChar\tendChar\theadId\thead\tdepRel\tfeats') +sPubF.write('sent\tid\tword\tlemma\tUPoS\tXPoS\tstartChar\tendChar\theadId\thead\tdepRel\tfeats') +sPubF.write("\r\n") + +# When depRel == "goeswith" + +for sentId, sent in enumerate(doc.sentences): + #print(*[f'{1+sentId}\t{word.id}\t{word.text}\t{word.lemma}\t{word.upos}\t{word.xpos}\t{word.start_char}\t{word.end_char}\t{word.head}\t{sent.words[word.head-1].text if word.head > 0 else "(root)"}\t{word.deprel}\t{word.feats if word.feats else "_"}' for word in sent.words], sep='\n') + for word in sent.words: + #if len(word.text) > 0: + #wordId = word.id + #wordText = word.text + depRel = word.deprel + if depRel == "goeswith": + print(*[f'****{1+sentId}\t{word.id}\t{word.text}\t{word.deprel}' for word in sent.words], sep='\n') + #continue + # + sPubOut = str(1+sentId) + "\t" + sPubOut += str(word.id) if word.id > 0 else "" + sPubOut += "\t" + sPubOut += ( str(word.text) if word.text.isnumeric() else word.text ) + sPubOut += "\t" + if word.lemma is not None: + sPubOut += ( str(word.lemma) if word.lemma.isnumeric() else word.lemma) + # + sPubOut += "\t" + sPubOut += ( str(word.upos) if word.upos.isnumeric() else word.upos ) + sPubOut += "\t" + sPubOut += ( str(word.xpos) if word.xpos.isnumeric() else word.xpos ) + sPubOut += "\t" + sPubOut += str(word.start_char) if word.start_char >= 0 else "" + sPubOut += "\t" + sPubOut += str(word.end_char) if word.end_char >= 0 else "" + sPubOut += "\t" + sPubOut += str(word.head) if word.head >= 0 else "" + sPubOut += "\t" + if word.head >= 0: + sPubOut += ( sent.words[word.head-1].text if word.head > 0 else "(root)" ) + # + sPubOut += "\t" + if word.deprel is not None: + sPubOut += word.deprel + # + sPubOut += "\t" + sPubOut += word.feats if word.feats else "_" + #sPubF.write(str(1+sentId) + "\t" + str(word.id) + "\t" + word.text + "\t" + word.lemma + "\t" + word.upos + "\t" + word.xpos + "\t" + str(word.start_char) + "\t" + str(word.end_char) + "\t" + str(word.head) + "\t" + sent.words[word.head-1].text if word.head > 0 else "(root)" + "\t" + word.deprel + "\t" + word.feats if word.feats else "_") + sPubF.write(sPubOut) + sPubF.write("\r\n") + # + # +# + +""" +2023-02-03 21:19:34 INFO: Loading these models for language: en (English): +============================ +| Processor | Package | +---------------------------- +| tokenize | combined | +| pos | combined | +| lemma | combined | +| depparse | combined | +| sentiment | sstplus | +| constituency | wsj | +| ner | ontonotes | +============================ + +2023-02-03 21:19:34 INFO: Use device: cpu +2023-02-03 21:19:34 INFO: Loading: tokenize +2023-02-03 21:19:34 INFO: Loading: pos +2023-02-03 21:19:35 INFO: Loading: lemma +2023-02-03 21:19:35 INFO: Loading: depparse +2023-02-03 21:19:35 INFO: Loading: sentiment +2023-02-03 21:19:35 INFO: Loading: constituency +2023-02-03 21:19:36 INFO: Loading: ner +2023-02-03 21:19:36 INFO: Done loading processors! +""" + +sPubF.close() + diff --git a/Archive/SubmitToCloudWhisper_textbook.py b/Archive/SubmitToCloudWhisper_textbook.py new file mode 100644 index 0000000..444aea6 --- /dev/null +++ b/Archive/SubmitToCloudWhisper_textbook.py @@ -0,0 +1,808 @@ +#! ...python3 +# cd "/mnt/d/Documents/FEP-AI/2022 Livestreams/ls042/ls042-0" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" "ls042-0" "http://crisiscenter.us/AILab01/2022Livestreams" "ls042-0.m4a" | tee ls042-0_whisper_m4a.json & + +# cd "/mnt/d/Documents/FEP-AI/2021 Livestreams/ls025" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" "ls025-2" "http://crisiscenter.us/AILab01/2022Gueststreams" "ls025-2.m4a" | tee ls025-2.m4a.json & + +# cd "/mnt/d/Documents/FEP-AI/2022 GuestStream/Mass 2022 GuestStreams" +# #python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" "gs014-1" "http://crisiscenter.us/AILab01/2022Gueststreams" "gs014-1.m4a" | tee gs014-1.m4a.json & + +#cd "/mnt/d/Documents/FEP-AI/2022 Livestreams/Mass 2022 Livestreams" + #python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls048-1 "http://crisiscenter.us/AILab01/2022Livestreams" "ls048-1.m4a" | tee ls048-1.m4a.json & + # myID['ls048-0']= "rx1rvgss4t-2e6c-46ee-a0d4-42777283a9b1" + # myID['ls048-1']= 'rxytoplp16-7b8b-41a6-be1b-78a0a837d8d4' + +#cd "/mnt/d/Documents/FEP-AI/2022 Livestreams/Mass 2022 Livestreams" + #python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls048-1 "http://crisiscenter.us/AILab01/2022Livestreams" "ls048-1.m4a" | tee ls048-1.m4a.json & + +#cd "/mnt/d/Documents/FEP-AI/2021 Livestreams/ls016/" rxzfu6wsa1-06f3-4028-8bf7-355d7f61eb00 + #python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls016-1 "http://crisiscenter.us/AILab01/2022Livestreams" "ls016.m4a" | tee ls016-1.m4a.json & + +#D:\Documents\FEP-AI\Active Inference Podcast\Transcribe via Whisper.json +#call with python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/Transcribe via Whisper.py" ls037-0 "http://crisiscenter.us/AILab01/2022Livestreams" "ls037-0.m4a" rs3z2z81w6-4507-4918-b001-7c08ebad22a6 +#call with python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/Transcribe via Whisper.py" ls037-1 "http://crisiscenter.us/AILab01/2022Livestreams" "ls037-1.mp3" | tee ls037-1.mp3.json rsury59afm-90b2-4049-9d08-cbb116e36808 +#cd /mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #037 Stephen Mann - Free Energy A User's Guide/ls037-2 + #python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls037-2 "http://crisiscenter.us/AILab01/2022Livestreams" "ls037-2.m4a" | tee ls037-2.m4a.json +#cd /mnt/d/Music/Fugs + #python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" PBF "http://crisiscenter.us/misc" "DrStrangelovePreciousBodilyFluids.m4a" | tee PBF.m4a.json rsuh9skgre-a056-486e-8138-2e6608d21f04 +#cd "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #040 - Chris Fields... A free energy principle for generic quantum systems/ls040-1" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls040-1 "http://crisiscenter.us/AILab01/2022Livestreams" "ls040-1.m4a" | tee ls040-1.m4a.json + +#cd "/mnt/d/Documents/FEP-AI/2022 Livestreams\ActInf Livestream #041 - Axel Constant - Extended Active Inference beyond Skulls/ls040-1" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls041-1 "http://crisiscenter.us/AILab01/2022Livestreams" "ls041-1.m4a" | tee ls041-1.m4a.json +#cd "/mnt/d/Documents/FEP-AI/2022 Livestreams/ls042/ls042-0" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/SubmitToCloudWhisper.py" ls042-0 "http://crisiscenter.us/AILab01/2022Livestreams" "ls042-0.m4a" | tee ls042-0.m4a.json + + +# For more logic, see "Transcribe ls036 Modelling ourselves.txt" in "D:\Documents\FEP-AI\2022 Livestreams\ActInf Livestream #036 Modeling Ourselves" + +import requests +import time +import sys +import math +import csv +import json + +#call with python3 - BerlinSym2021KJFKey "http://crisiscenter.us/AILab01/Karl_Friston_Applied_Active_Inference_Symposium_2021-06-22" "Quadrille.wav" +#call with python3 - quadriTest "http://crisiscenter.us/AILab01/Karl_Friston_Applied_Active_Inference_Symposium_2021-06-22" "Quadrille.wav" rzw49dpr1n-4856-4172-adf4-e502720c93de + +#call with python3 - ls051-0 "http://crisiscenter.us/AILab01/2022Livestreams" "ls051-0.wav" rskfsnu6hj-8e56-4c7d-a4d1-76aa04ab873a +#call with python3 - ls051-0-2 "http://crisiscenter.us/AILab01/2022Livestreams" "ls051-0-2.mp3" rsk599qwnx-7e0e-49c2-bafd-8cb0ad4745db + +#python3 - ls036-0 "http://crisiscenter.us/AILab01/2022Livestreams" "ls036-0.m4a" +#call with python3 - ls036-2 "http://crisiscenter.us/AILab01/2022Livestreams" "ls036-2.m4a" + +if __name__ == "__main__": + print(f'Arguments count: {len(sys.argv)}') + if len(sys.argv) < 3: + print("Need at least docLabel, onlinePath, and onlineFile; exiting!") + quit() + + +#for i, arg in enumerate(sys.argv): +# print(f'Argument {i:>6}: {arg}') + +docLabel = sys.argv[1] +onlinePath = sys.argv[2] +onlineFile = sys.argv[3] +print("docID, onlinePath, onlineFile " + "'" + docLabel + "', '" + onlinePath + "', '" + onlineFile + "'") +if len(sys.argv) > 4: + outputPath = sys.argv[4] + print("outputPath: " + "'" + outputPath + "'") + + + +# --------------------- + + +def ToDisplayTime(tt): + ts=float(tt) + h0=int(ts/3600000.0) + hh="" + if h0 > 9: + hh = str(100+h0) + hh = hh[1:3] + ":" + elif h0 > 0: + hh = str(h0) + ":" + + m0=int( (ts-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ts - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + to_time= hh + mm[1:3] + ":" + ss[1:3] + return to_time + + +def ToSRTTime(tt): + ts=float(tt) + h0=int(ts/3600000.0) + hh = str(100+h0) + m0=int( (ts-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ts - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ts - (3600000.0*h0) - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= hh[1:3] + ":" + mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + + + +# --------------------- + + +#"audio_url": " + onlinePath + "/" + onlineFile + ", +#"audio_url": "http://crisiscenter.us/AILab01/Karl_Friston_Applied_Active_Inference_Symposium_2021-06-22/Quadrille.wav", + +endpoint = "https://api.assemblyai.com/v2/transcript" +audio_url = onlinePath + "/" + onlineFile + +# "speaker_labels": True, + +# for a fatter list - one containing an error - see "SubmitToCloudWhisper - Copy (13) - Try word_boost, spell again.py" + +#following word_boost list was 'generated' from YouTube SRT using srtToCsv.py (plus some filtering in a spreadsheet) +json = { + "audio_url": audio_url, + "word_boost": [ +"Thomas Parr", +"Lagrange", +"Lagrangian", +"centripetal force", +"Beren Millidge", +"Anil Seth", +"Axel Constant", +"Andy Clark", +"Michael Kirchhoff", +"Lancelot Costa", +"Axel Constant", +"Andy Clark", +"Michael Kirchhoff", +"Tim Verbelen", +"Sean Carroll", +"Mindscape", +# +"ActInf Lab GuestStream", +"ActInf Lab Livestream", +"ActInf Lab MathStream", +"ActInf Lab ModelStream", +"ActInf Lab OrgStream", +"ActInf Lab project", +"ActInf Livestream", +"ActInf", +"ActInfLab project", +"Active Inference", +"Active Inference GuestStream", +"Active Inference Institute", +"Active Inference Lab", +"Active Inference Livestream", +"Active Inference MathStream", +"Active Inference ModelStream", +"Active Inference OrgStream", +"Bayesian", +"Bayesian inference", +"Bleu", +"Daniel", +"Dean", +"Free Energy Principle", +"Friston", +"Friston blanket", +"Karl Friston", +"Karl J. Friston", +"Markov blanket", +"Markov decision", +"Stephen", +"YouTube", +# ----------------- +"Principle of Least Action", +"Least Action", +"action oriented representation", +"action planning", +"action prediction", +"action", +"active states", +"active", +"activity", +"affordance", +"agency", +"agent", +"agreement", +"allostasis", +"allostat", +"ambiguity", +"aspects", +"assumptions", +"asymmetry", +"attention", +"Bayesian statistics physics", +"behavior", +"belief updating", +"Bellman equation", +"Bijan Khezri", +# +"I", +"I'll", +"I've", +"I'm" +], + "custom_spelling": [ +{"from": ["parr"], "to": "Parr"}, +{"from": ["beren"], "to": "Beren"}, +{"from": ["millidge"], "to": "Millidge"}, +{"from": ["anil"], "to": "Anil"}, +{"from": ["pease","peas"], "to": "Pease"}, +{"from": ["seth"], "to": "Seth"}, +{"from": ["verbelen"], "to": "Verbelen"}, +{"from": ["actinf"], "to": "ActInf"}, +{"from": ["bayesian"], "to": "Bayesian"}, +{"from": ["daniel"], "to": "Daniel"}, +{"from": ["friston"], "to": "Friston"}, +{"from": ["markov"], "to": "Markov"}, +{"from": ["youtube"], "to": "YouTube"}, +{"from": ["gueststream"], "to": "GuestStream"}, +{"from": ["livestream"], "to": "Livestream"}, +{"from": ["mathstream"], "to": "MathStream"}, +{"from": ["modelstream"], "to": "ModelStream"}, +{"from": ["orgstream"], "to": "OrgStream"}, +# +{"from": ["bleu"], "to": "Bleu"}, +{"from": ["google"], "to": "Google"}, +{"from": ["elizabethan"], "to": "Elizabethan"}, +{"from": ["aristotelian"], "to": "Aristotelian"}, +{"from": ["i"], "to": "I"}, +{"from": ["i'm"], "to": "I'm"}, +{"from": ["i'll"], "to": "I'll"}, +{"from": ["i've"], "to": "I've"}, +{"from": ["shakespeare"], "to": "Shakespeare"}, +#------------------- +{"from": ["lagrange"], "to": "Lagrange"}, +{"from": ["lagrangian"], "to": "Lagrangian"} +], + #"summarization": True, + #"summary_type": "bullets", + "speaker_labels": True, # not yet supported for Portuguese + "language_model": "large", + "entity_detection": True, + "auto_highlights": True, + "iab_categories": True, + "auto_chapters": True, + "sentiment_analysis": True, + "language_code": "en_us" #"pt" +} +headers = {"authorization": "a14f484d11984e00bf7105cda4bc0c9a","content-type": "application/json"} +response = requests.post(endpoint, json=json, headers=headers) +#print(response.json()) +jj=response.json() +myId=jj.get('id') +print(myId) +myStatus=jj.get('status') +print(myStatus) +time.sleep(30) + + +import requests +import time +import sys +import math +import csv +#myId = "rsuh9skgre-a056-486e-8138-2e6608d21f04" + +while myStatus == "queued" or myStatus == "processing": + time.sleep(120) + endpoint = "https://api.assemblyai.com/v2/transcript/" + myId + headers = {"authorization": "a14f484d11984e00bf7105cda4bc0c9a"} + response = requests.get(endpoint, headers=headers) + #print(response.json()) + jj=response.json() + myStatus=jj.get('status') + print(myStatus) + + +print() +print() +print("Dump JSON response:") +print(jj) +print() +print(myId) +print(myStatus) + +if myStatus != "completed": + myError = jj.get('error') + print() + print("Bad results from last main poll. Call if you find work.") + print(myError) + quit() + +# ----------- words (apparently always identical to those from paragraphs) ---------- + + +wordFileName = docLabel + "_" + onlineFile + ".words.csv" +#wwf = open(wordFileName, "w") + +#words = jj.get('words') + +#for count, word in enumerate(words): +# wtext=word.get('text') +# wstart=word.get('start') +# wend=word.get('end') +# wconfid=word.get('confidence') +# wspeaker=word.get('speaker') +# # +# wordOut = str(wstart) + "\t" + str(wend) + "\t" +# if wspeaker != None: +# wordOut = wordOut + wspeaker +# +# # +# wordOut = wordOut + "\t" + str(wconfid) + "\t" +# if wtext != None: +# wordOut = wordOut + wtext +# +# # +# #wordOut = str(wstart) + "\t" + str(wend) + "\t" + wspeaker + "\t" + str(wconfid) + "\t" + wtext +# wwf.write(wordOut) # #print(utterOut) , delimiter='\t', lineterminator='\t\n' +# wwf.write("\r\n") + +#wwf.close() + + +# ----------- IAB categories ---------- + +iabCats = jj.get('iab_categories_result') +catStatus=iabCats.get('status') +if catStatus == 'success': + catDetFileName = docLabel + "_" + onlineFile + ".categoryDetails.csv" + cdf = open(catDetFileName, "w") + catDetOut = "start" + "\t" + "end" + "\t" + 'relevance' + "\t" + 'label' + cdf.write(catDetOut) + cdf.write("\r\n") + catDetails=iabCats.get('results') + for rCount, cDKey in enumerate(catDetails): # retrieve by POSITION + #for count, cKey in enumerate(cDKey): # retrieve by KEY + cTKey = cDKey.get('timestamp') + #print(cTKey) + cStart = cTKey.get('start') # will use same timestamps for all label/relevance pairs + #print(cStart) + cEnd = cTKey.get('end') + #print(cEnd) + cLabels = cDKey.get('labels') + #print(cLabels) + for labelCount, labelPair in enumerate(cLabels): # retrieve by POSITION + cRelev = labelPair.get('relevance') + cLabel = labelPair.get('label') + catDetOut = str(cStart) + "\t" + str(cEnd) + "\t" + str(cRelev) + "\t" + str(cLabel) + #print(catDetOut) + cdf.write(catDetOut) # print(utterOut) , delimiter='\t', lineterminator='\t\n' + cdf.write("\r\n") + + + cdf.close() + + +# also (separately) save summaries (i.e. session-level IAB categories) +if catStatus == 'success': + catFileName = docLabel + "_" + onlineFile + ".categories.csv" + ccf = open(catFileName, "w") + catOut="key" + "\t" + "relevance" + ccf.write(catOut) # print(utterOut) , delimiter='\t', lineterminator='\t\n' + ccf.write("\r\n") + summaries=iabCats.get('summary') + summKeys=summaries.keys() + for count, cKey in enumerate(summKeys): + cRelev=summaries.get(cKey) + catOut=cKey + "\t" + str(cRelev) + ccf.write(catOut) # print(utterOut) , delimiter='\t', lineterminator='\t\n' + ccf.write("\r\n") + + + ccf.close() + + +# ----------- chapters ---------- +chapterVec = [] +chapterVecs = [] +chapFileName = docLabel + "_" + onlineFile + ".chapters.csv" +ccf = open(chapFileName, "w") + +chapters = jj.get('chapters') # also insert timestamp +#write header +chapterOut = "start" + "\t" + "end" + "\t" + "startTime" + "\t" + "summary" + "\t" + "headline" + "\t" + "gist" +ccf.write(chapterOut) +ccf.write("\r\n") + +for count, chapter in enumerate(chapters): + cSummary=chapter.get('summary') + cHeadline=chapter.get('headline') + cGist=chapter.get('gist') + cStart=chapter.get('start') + cStartTime = ToDisplayTime(cStart) #supplement with legible timestamp + cEnd=chapter.get('end') + chapterOut = str(cStart) + "\t" + str(cEnd) + "\t" + str(cStartTime) + "\t" + cSummary + "\t" + cHeadline + "\t" + cGist + ccf.write(chapterOut) + ccf.write("\r\n") + chapterVec=[cStart, cEnd, cSummary, cHeadline, cGist] + chapterVecs.append(chapterVec) +ccf.close() + + +# ----------- sentiment analysis ---------- + +ss=jj.get('sentiment_analysis_results') +#print(ss) + +# Better to use CSV package throughout! +#with open('records.tsv', 'w', newline='') as tsvfile: +# writer = csv.writer(tsvfile, delimiter='\t', lineterminator='\n') +# for record in SeqIO.parse("/home/fil/Desktop/420_2_03_074.fastq", "fastq"): +# writer.writerow([record.id, record.seq, record.format("qual")]) + +sentimentFileName = docLabel + "_" + onlineFile + ".sentiments.csv" +ssf = open(sentimentFileName, "w") + +sentimOut = "start" + "\t" + "end" + "\t" + "speaker" + "\t" + 'sentiment' + "\t" + "confidence" + "\t" + "text" +ssf.write(sentimOut) # print(sentimOut) , delimiter='\t', lineterminator='\t\n' +ssf.write("\r\n") + +#with open(sentimentFileName, 'w', encoding='utf8', newline='') as csvfile: +# writer = csv.writer(csvfile, delimiter=',', lineterminator='\n') +# writer.writeheader(["start","end","speaker","sentiment","confidenct","text"]) +# #for record in SeqIO.parse("/home/fil/Desktop/420_2_03_074.fastq", "fastq"): +# writer.writerow([record.id, record.seq, record.format("qual")]) + +for count, sentim in enumerate(ss): + stext = sentim.get('text') + sstart = sentim.get('start') + send = sentim.get('end') + ssentim = sentim.get('sentiment') + sconfid = sentim.get('confidence') + sspeaker = sentim.get('speaker') + #sentimOut = str(sstart) + "\t" + str(send) + "\t" + sspeaker + "\t" + ssentim + "\t" + str(sconfid) + "\t" + stext + sentimOut = str(sstart) + "\t" + str(send) + "\t" + if sspeaker != None: + sentimOut = sentimOut + sspeaker + + # + sentimOut = sentimOut + "\t" + str(sconfid) + "\t" + stext + ssf.write(sentimOut) # print(sentimOut) , delimiter='\t', lineterminator='\t\n' + ssf.write("\r\n") + +ssf.close() + +# ----------- utterances ---------- + +utteranceFileName = docLabel + "_" + onlineFile + ".utterances.csv" +uuf = open(utteranceFileName, "w") + +utterOut = "start" + "\t" + "end" + "\t" + "speaker" + "\t" + "confidence" + "\t" + "text" +uuf.write(utterOut) # print(utterOut) , delimiter='\t', lineterminator='\t\n' +uuf.write("\r\n") + +utterances = jj.get('utterances') + +for count, utterance in enumerate(utterances): + uconfid = utterance.get('confidence') + uend = utterance.get('end') + uspeaker = utterance.get('speaker') + ustart = utterance.get('start') + utext = utterance.get('text') + #utterOut = str(ustart) + "\t" + str(uend) + "\t" + uspeaker + "\t" + str(uconfid) + "\t" + utext + utterOut = str(ustart) + "\t" + str(uend) + "\t" + if uspeaker != None: + utterOut = utterOut + uspeaker + + # + utterOut = utterOut + "\t" + str(uconfid) + "\t" + utext + uuf.write(utterOut) # print(utterOut) , delimiter='\t', lineterminator='\t\n' + uuf.write("\r\n") + +uuf.close() + + +# ----------- entities ---------- + +entityFileName = docLabel + "_" + onlineFile + ".entities.csv" +eef = open(entityFileName, "w") + +entityOut = "text" + "\t" + 'entity_type' + "\t" + "\t" + "start" + "\t" + "end" +eef.write(entityOut) +eef.write("\r\n") + +entities = jj.get('entities') +for count, entity in enumerate(entities): + eType=entity.get('entity_type') + eText=entity.get('text') + eStart=entity.get('start') + eEnd=entity.get('end') + entityOut = eText + "\t" + eType + "\t" + "\t" + str(eStart) + "\t" + str(eEnd) + eef.write(entityOut) + eef.write("\r\n") + + +eef.close() + + +#------- paragraphs ------------------- + + +#needs myId, docLabel, onlineFile +#myId ="rsuh9skgre-a056-486e-8138-2e6608d21f04" +#docLabel = "mo007-1-SP" +#onlineFile = "mo007-1.m4a" + +import requests +import time +import sys +import math +import csv + +endpoint = "https://api.assemblyai.com/v2/transcript/" + myId + "/paragraphs" +headers = {"authorization": "a14f484d11984e00bf7105cda4bc0c9a"} +response = requests.get(endpoint, headers=headers) +time.sleep(60) +kk=response.json() +print("") +print("") +print(" *** Response from /paragraphs call ***") +print(kk) +print("") +print(" *************************************") +print("") + +parags=kk.get("paragraphs") #fetch all paragraphs +paragCount = len(parags) #how many paragraphs? +#print(paragCount) +paragNum = 0 +wordPos = 0 + +paragraphFileName = docLabel + "_" + onlineFile + ".paragraphs.csv" +ppf = open(paragraphFileName, "w") + +rawParagFileName = docLabel + "_" + onlineFile + ".rawParag.csv" +rppf = open(rawParagFileName, "w") + +current_speaker = "(Undefined Speaker)" +paragSpeakers = dict() + +paragSpeakerFileName = docLabel + "_" + onlineFile + ".paragSpeakers.csv" +psf = open(paragSpeakerFileName, "w") + + +paragStartings = [] +rawParags = {} +speakerCount = 0 +speakerTurns = 0 +oldWEnd = 0 # end of preceding word; matches current_speaker +# needed to end preceding paragraph when change of speaker triggers end-of-paragraph event + +#Also record PARAGRAPH version of words: Speaker can VARY within paragraph! # also insert timestamp, "Corrected Text". +paragWordFileName = docLabel + "_" + onlineFile + ".paragWords.csv" +pwf = open(paragWordFileName, "w") +wordOut = "start" + "\t" + "end" + "\t" + "speaker" + "\t" + "confidence" + "\t" + "paragNum" + "\t" + "paragWordCount" + "\t" + "wordPos" + "\t" + "text" +pwf.write(wordOut) +pwf.write("\r\n") + +rawParagOut = "start" + "\t" + "end" + "\t" + "paragNum" + "\t" + "speaker" + "\t" + "pconfid" + "\t" + "wordPos" + "\t" + "paragWordPos" + "\t" + "paragFirstWordCount" + "\t" + "paragLastWordCount" +rppf.write(rawParagOut) +rppf.write("\r\n") + +#Column headers +paragOut = "start" + "\t" + "end" + "\t" + "paragNum" + "\t" + "speaker" + "\t" + "confidence" + "\t" + "startTime" + "\t" + "wordCount" + "\t" + "text" +ppf.write(paragOut) +ppf.write("\r\n") + +#if docLabel in paragSpeakers: # re-run; delete old slot +# paragSpeakers[docLabel] = { } +# print() + +for p0 in parags: + paragNum += 1 + paragWordPos = 0 # count of words within paragraph + text=p0.get('text') #text of paragraph + start=p0.get('start') #starting milisecond of paragraph + paragStartings.append(start) + pStartTime = ToDisplayTime(start) # supplement with legible timestamp + end=p0.get('end') #text of paragraph + pconfid = p0.get('confidence') #paragraph-level confidence + words=p0.get('words') #list of words + wordCount = len(words) + w1_0=words[0] #first word - use only "speaker" of first word + sp=w1_0.get('speaker') #Label entire paragraph with first speaker + + # Record start of each speech turn (usually several per speaker) + if sp != current_speaker: + current_speaker = sp + speakerTurns += 1 + if sp in paragSpeakers: + paragSpeakers[sp].append(start) + else: + paragSpeakers[sp] = [start] # First speech turn only + speakerCount += 1 + # + # + paragFirstWordCount = wordPos + 1 #position within document, of first word in paragraph + + for wCount, word in enumerate(words): # Now extract all info on included words + wordPos += 1 #position of word within document + paragWordPos += 1 #position of word within paragraph + wtext=word.get('text') + wstart=word.get('start') + wend=word.get('end') + wconfid=word.get('confidence') + wspeaker=word.get('speaker') + #wordOut = str(wstart) + "\t" + str(wend) + "\t" + wspeaker + "\t" + str(wconfid) + "\t" + wtext + wordOut = str(wstart) + "\t" + str(wend) + "\t" + if wspeaker != None and len(wspeaker)>0: + wordOut += wspeaker + + wordOut += "\t" + str(wconfid) + "\t" + str(paragNum) + "\t" + str(paragWordPos) + "\t" + str(wordPos) + "\t" + wtext + pwf.write(wordOut) # print(utterOut) , delimiter='\t', lineterminator='\t\n' + pwf.write("\r\n") + # + paragLastWordCount = wordPos # count of most recently-counted word within document, is last word in paragraph + + paragOut = str(start) + "\t" + str(end) + "\t" + str(paragNum) + "\t" + if sp != None and len(sp) > 0: + paragOut += sp + # + paragOut += "\t" + str(pconfid) + paragOut += "\t" + str(pStartTime) + + paragOut += "\t" + str(wordCount) + paragOut += "\t" + text # '+ "\t" + text' for manual editing. IF you use a spreadsheet, REMEMBER to set the "text" columns very wide before saving!! + ppf.write(paragOut) + ppf.write("\r\n") + + # parag start/end millisecond, parag #, first speaker, confid, # words in parag, (document-level) start/last word # + rawParags.update( {start: [end, paragNum, sp, pconfid, wordPos, paragWordPos, paragFirstWordCount, paragLastWordCount] } ) + #rawParags.update( {start: {'end':wend, 'paragNum':paragNum, 'speaker':wspeaker, 'confid':wconfid, 'wordPos':wordPos, 'paragFirstWordCount':paragFirstWordCount} } ) + rawParagOut = str(start) + "\t" + str(end) + "\t" + str(paragNum) + "\t" + sp + "\t" + str(pconfid) + "\t" + str(wordPos) + "\t" + str(paragWordPos) + "\t" + str(paragFirstWordCount) + "\t" + str(paragLastWordCount) + rppf.write(rawParagOut) + rppf.write("\r\n") + + +#display first occurrence of each speaker, with first time (in three formats) +#print("paragSpeakers:") +#print(paragSpeakers) +#{'A': [1200, 3000], 'B': [2400]} + +speakerTimeOut = 'docLabel' + "\t" + "sp" + "\t" + "myTime" + "\t" + "myTimeDisplay" + "\t" + "myTimeSRT" +psf.write(speakerTimeOut) +psf.write("\r\n") + +paragSpeakerKeys=paragSpeakers.keys() +for sp in paragSpeakerKeys: + timeList = paragSpeakers.get(sp) + for tcc, myTime in enumerate(timeList): + #paragSpeakers[docLabel] = {start: sp} + speakerTimeOut = docLabel + "\t" + sp + "\t" + str(myTime) + "\t" + ToDisplayTime(myTime) + "\t" + ToSRTTime(myTime) + psf.write(speakerTimeOut) + psf.write("\r\n") + # + +# +ppf.close() +pwf.close() +psf.close() +rppf.close() + +print(" Speakers (from Paragraphs output):") +print(paragSpeakerKeys) +for sp in paragSpeakerKeys: + timeList = paragSpeakers.get(sp) + print(sp + " @ " + ToDisplayTime(timeList[0])) + +#--------- Sentence(s) ----------------- + +#myId="rs8dx3ybuk-75db-405d-950b-560ec269d003" + +endpoint = "https://api.assemblyai.com/v2/transcript/" + myId + "/sentences" +headers = { + "authorization": "a14f484d11984e00bf7105cda4bc0c9a"} +sResponse = requests.get(endpoint, headers=headers) +time.sleep(30) +sss=sResponse.json() +myStatus=sss.get('status') +print(myStatus) +print("") +print("") +print(" *** Response from /sentences call ***") +print(sss) +print("") +print(" *************************************") +print("") + +paragTimes = [] +paragTimes = rawParags.keys() # Key (i.e. paragraph-start time) may be all we need hereafter + +current_speaker = "(Undefined Speaker)" +wordPos = 0 # starting thru document from top + +sents=sss.get("sentences") #fetch all sentences +sentCount = len(sents) #how many sentences? +sentNum = 0 + +sentenceFileName = docLabel + "_" + onlineFile + ".sentences.csv" +sssf = open(sentenceFileName, "w") +#Column headers +sentOut = "start" + "\t" + "end" + "\t" + "sentNum" + "\t" + "speaker" + "\t" + "confidence" + "\t" + "text" +sssf.write(sentOut) +sssf.write("\r\n") + +sentWordFileName = docLabel + "_" + onlineFile + ".sentWords.csv" +sswf = open(sentWordFileName, "w") +sentWOut = "start" + "\t" + "end" + "\t" + "sentNum" + "\t" + "speaker" + "\t" + "confidence" + "\t" "wordPosSent" + "\t" + "wordPosDoc" + "\t" + "text" +sswf.write(sentWOut) +sswf.write("\r\n") + +for s0 in sents: + sentNum += 1 + sentWordPos = 0 # no words yet seen in this sentence + text=s0.get('text') #text of sentence + start=s0.get('start') #text of sentence + end=s0.get('end') #text of sentence + pconfid = s0.get('confidence') #sentence-level confidence + w1=s0.get('words') #list of words + w1_0=w1[0] #first word - use only "speaker" of first word + sp=w1_0.get('speaker') #Label entire sentence with first speaker + # + if str(start) in paragTimes: + paragBreak = True + paragNum = rawParags.get('paragNum') + else: + paragBreak = False + paragNum = 0 + # + for wCount, word in enumerate(w1): # Now extract all info on included words + wordPos += 1 #position of word within document + sentWordPos += 1 #position of word within sentence + wtext=word.get('text') + wstart=word.get('start') + wend=word.get('end') + wconfid=word.get('confidence') + wspeaker=word.get('speaker') + sentenceWords = [wstart, wend, sentNum, wspeaker, wconfid, sentWordPos, wordPos, wtext] + #wordOut = str(wstart) + "\t" + str(wend) + "\t" + wspeaker + "\t" + str(wconfid) + "\t" + wtext + wordOut = str(wstart) + "\t" + str(wend) + "\t" + str(sentNum) + "\t" + if wspeaker != None and len(wspeaker)>0: + wordOut += wspeaker + # + if paragNum > 0: + wordOut += str(paragNum) + # + wordOut += "\t" + str(wconfid) + "\t" + str(sentWordPos) + "\t" + str(wordPos) + "\t" + wtext + sswf.write(wordOut) + sswf.write("\r\n") + # sentOut = str(start) + "\t" + str(end) + "\t" + sp + "\t" + str(pconfid) + "\t" + text + sentOut = str(start) + "\t" + str(end) + "\t" + str(sentNum) + "\t" + if sp != None: # 'sentence-level speaker.' Don't rely on this at word level. + sentOut += sp + # + sentOut += "\t" + str(pconfid) + "\t" + text + sssf.write(sentOut) + sssf.write("\r\n") + # + #if (sp != current_speaker) or (start in paragStartings): + # print("Magic new paragraph, speaker '" + wspeaker + " " + str(wstart)) + # + +sssf.close() +sswf.close() + + +# ------------ SRT ----------- + +import requests +import time +import sys +import math +import csv + +#docLabel = "parseSRT" +#onlineFile = "ls040-0" + +srtFileName = docLabel + "_" + onlineFile + ".srt" +srtf = open(srtFileName, "w") + +#myId="rsfzjbpypn-f1ff-4dc4-9aca-0526544dc4ed" + +endpoint = "https://api.assemblyai.com/v2/transcript/" + myId + "/srt?chars_per_caption=40" # "/srt?chars_per_caption=40" "/paragraphs" +headers = {"authorization": "a14f484d11984e00bf7105cda4bc0c9a"} +sResponse = requests.get(endpoint, headers=headers) + +srtf.write(sResponse.text) +srtf.write("\r\n") + +srtf.close() + +#time.sleep(30) +#srts=sResponse.json() +#print(srts) +#myStatus=srts.get('status') +#print(myStatus) + + +#srtOut = srtOut + "\t" + str(pconfid) + "\t" + text +#srtf.write(srtOut) + +print("Thanks for the call!") +quit() diff --git a/Archive/sentencesToTranscripts.py b/Archive/sentencesToTranscripts.py new file mode 100644 index 0000000..e8e75b5 --- /dev/null +++ b/Archive/sentencesToTranscripts.py @@ -0,0 +1,889 @@ +# +# After "sentencesToTranscripts - Copy (21).py" add SRT-Speaker logic: +# generate fresh SRT *_transcript.srt from *.sentences.csv); insert speaker names formulated from +# +# cd "/mnt/d/Documents/FEP-AI/2022 GuestStream/Mass 2022 GuestStreams" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/sentencesToTranscripts.py" "gs014-1" "." "gs014-1_gs014-1.m4a.sentences.csv" | tee gs014-1.m4a_transcript.json +# +# cd "/mnt/d/Documents/FEP-AI/2022 GuestStream/Mass 2022 GuestStreams" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/sentencesToTranscripts.py" "gs014-1" "." "gs014-1_gs014-1.m4a.sentences.csv" | tee gs014-1.m4a_transcript.json +# +#cd "/mnt/d/Documents/FEP-AI/2022 ModelStream/mo007/SPtest" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/sentencesToTranscripts.py" mo007-1 "." "mo007-1_mo007-1.mp3.sentences.csv" | tee mo007-1_publish.txt +# +#AllSpeakers "/mnt/d/Documents/FEP-AI/Active Inference Podcast/AllSpeakers.csv" + +import csv +import time +import sys +import math +import json +from html.parser import HTMLParser + +if __name__ == "__main__": + print(f"Arguments count: {len(sys.argv)}") + if len(sys.argv) == 1: + print("sentencesToTranscripts. Needs parameters docLabel (key binding references to this doc),") + print("inSentDir (path to incoming files), inSentFile (name of driver file *.sentences.csv).") + print("Optional params outDir (defaults to working directory '.'), speakers (defaults to a central CSV identifying all speakers).") + print("Created in outDir: *_transcript.txt, *_built.srt, *_built.xhtml") + print("If inSentDir holds a *.paragraphs.csv file, it's used to force paragraph ends.") + quit() + elif len(sys.argv) < 4: + print("Need at least docLabel, inSentDir, and inSentFile; optional outDir, speakers. Exiting!") + quit() + +#File references: +# inSentDir/inSentFile Driver +# inSpeakerDir/inSpeakers When mappings known +# [inSentDir]/inWords Improves timestamp splitting; optional +# outDir/ One destination for everything +#Parameters: +# charsPerCaption For SRT: Max line len in chars + +charsPerCaption = 40 # cloned from AssemblyAI default - allow override from command line! +lastMDTs = -1 # initialize last MarkDown timestamp (any possible value is later!) + +#outDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #035 A tale of Two architectures/ls035-0/publish" + +mDPubF = "" +pPubF = "" +sPubF = "" +srtPubF = "" + +inSpeakerDir = "/mnt/d/Documents/FEP-AI/Active Inference Podcast/" +inSpeakers = "AllSpeakers.csv" + +docLabel = sys.argv[1] +inSentDir = sys.argv[2] +inSentFile = sys.argv[3] +print("docLabel, inSentDir, inSentFile " + "'" + docLabel + "', '" + inSentDir + "', '" + inSentFile + "'") + +#inSentDir = "/mnt/d/Documents/2022 Org Streams/os003/" +inParagFile = inSentFile.replace('.sentences.', '.paragraphs.') + +if len(sys.argv) > 4: + outDir = sys.argv[4] +else: + outDir = "." #publish to working directory! + +print("outDir: " + "'" + outDir + "'") + +if len(sys.argv) > 5: + speakerFile = sys.argv[5] +else: + speakerFile = "/mnt/d/Documents/FEP-AI/Active Inference Podcast/AllSpeakers.csv" + +print('speakers File: ' + "'" + speakerFile + "'") + +# globals +speakerDesc = {} +srtSpeaker = "" +srtPosCount = 0 +srtStartTime = 0 +srtEndTime = 0 + +# ++++++ notes ++++++ + +#create new version of "sentencesToTranscripts.py" (of 12/28, 12:48) + +#BUILDING WORD_BOOST LIST + +#Exclude all digit-only.z +#Select all base forms whose first character is always cap as "capitalized" +# Enter all as word_boost +# Enter all single word as spelling +#Decrease the cutoff for number of occurrence, starting with eight, until the next batch will take you over 1000. +#Maybe when you hit that zone, you can exclude "common nouns" and try for a last tranch that keeps you below the largest allowed number of boosts. +# +#prepare to compare to Google/YouTube word list +#confidSentWordList = sentWordVec +#confidSentWordList.sort(reverse=True, key = lambda x: x[3]) # descending by confidence +#print(confidSentWordList) + +#where the fourth component of sentenceWords is confidence, the following gives the highest-confidence words at the top: +#sentenceWords.sort(reverse=True, key = lambda x: x[3]) + +# "Correct Whisper per YouTube (ls038-2).ods" + + +# ----- notes ----- + + + +# ------- Utility functions -------------- + +def hhMmSsToTime(ts): + tsLen = len(ts) + print("in hhMmSsToTime; ts/tsLen:") + print(ts) + print(tsLen) + if tsLen == 8: # hh:mm:ss + hh = int(ts[0:2]) + mm = int(ts[3:5]) + ss = int(ts[6:8]) + to_time= 3600000*hh + 60000*mm + 1000*ss + return to_time + elif tsLen == 7: # h:mm:ss + hh = int(ts[0:1]) + mm = int(ts[2:4]) + ss = int(ts[5:7]) + to_time= 3600000*hh + 60000*mm + 1000*ss + return to_time + elif tsLen == 5: # mm:ss + mm = int(ts[0:2]) + ss = int(ts[3:5]) + to_time= 60000*mm + 1000*ss + return to_time + elif tsLen == 4: # m:ss + mm = int(ts[0:1]) + ss = int(ts[2:4]) + to_time= 60000*mm + 1000*ss + return to_time + else: + return 9999999 + # +# + + + +def ToDisplayTime(tt): + ts=float(0.0+int(tt)) + h0=int(ts/3600000.0) + hh="" + if h0 > 9: + hh = str(100+h0) + hh = hh[1:3] + ":" + elif h0 > 0: + hh = str(h0) + ":" + + m0=int( (ts-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ts - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + to_time= hh + mm[1:3] + ":" + ss[1:3] + return to_time + + +def ToSRTTime(tt): + ts=float(0.0+int(tt)) + h0=int(ts/3600000.0) + hh = str(100+h0) + m0=int( (ts-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ts - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ts - (3600000.0*h0) - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= hh[1:3] + ":" + mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + + +def secToTime(ss): + if ss >= 3600000: + h0=int(ss/3600000.0) + hh = str(100+h0) + m0=int( (ss-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ss - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ss - (3600000.0*h0) - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= hh[1:3] + ":" + mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + else: + m0=int( ss / 60000.0) + mm=str(100+m0) + s0=int( (ss - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ss - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + # +# + + + +# ------- "Business" functions -------------- + +def speakerIdToName(doc, id, myTime): +# Default; override if possible from inSpeakers + #print("ord, len of '" + id) + #print(ord(id)) + #print(len(id)) + if len(id) > 1: # speaker already spelled out in 'sentences' input + return id + # + speaker = "Speaker " + id # default + #print("speakerDesc") + #print(speakerDesc) + spDesc = speakerDesc.get(id) + #print("spDesc") + #print(spDesc) + if spDesc is not None: + dName = spDesc.get('displayedName') + #print("dName") + #print(dName) + if dName is not None and len(dName)>0: + speaker = dName + # + # + return speaker + # +# + +def writeToMD(textOut, lineCount, mySpeakerName, startTime, endTime, myParagBreak): + global lastMDTs + #print("In writeToMD, lineCount:") + if len(mySpeakerName) > 0: + mDPubF.write("\r\n" + ToDisplayTime(startTime) + " _" + mySpeakerName + ":_") + mDPubF.write("\r\n") + mDPubF.write("\r\n") + mDPubF.write(textOut) + mDPubF.write("\r\n") + lastMDTs = startTime + elif myParagBreak: + print("parag hit in writeToMD " + str(startTime)) + mDPubF.write("\r\n" + ToDisplayTime(startTime) + " " + textOut) + mDPubF.write("\r\n") + lastMDTs = startTime + elif (0 + startTime) > (lastMDTs + 60000): + print("60-second hit in writeToMD " + str(startTime)) + mDPubF.write("\r\n" + ToDisplayTime(startTime) + " " + textOut) + mDPubF.write("\r\n") + lastMDTs = startTime + else: + mDPubF.write(textOut) + mDPubF.write("\r\n") + # +# + + +def writeToSrt(textOut, lineCount, mySpeakerName, startTime, endTime): + print("In writeToSrt, lineCount:") + print(lineCount) + myLineCount = lineCount + if len(mySpeakerName) == 0: + textRem = "" + else: + textRem = mySpeakerName + ": " # We will count length of speaker name as though it were audible. + # This may be convenient for viewing; but it makes + # detailed SRT time-labels useless for reconstructing speech timing + # + textRem += textOut.strip() + charsRem = len(textRem) + timeRem = endTime - startTime + msPerChar = (timeRem / charsRem) if charsRem > 0 else charsRem + oc1 = charsPerCaption+1 # lets us see a single character at end of window + oc2 = oc1 + 1 # sees single character at end of window + #if charsRem > 0: # should try to split last pair of lines evenly + while charsRem > 0: # should try to split last pair of lines evenly + if charsRem <= charsPerCaption: + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write(srtLine) + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + else: + prevSpace = textRem[0:oc2].rfind(" ") + if prevSpace >= 0: # leading integral block of text; dump thru following space + myText0 = textRem[0:prevSpace+1].strip() + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write(srtLine) + srtPubF.write("\r\n") + startTime = endTime + srtPubF.write(myText0) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") # close this SRT block + textRem = textRem[prevSpace:].strip() # remainder + charsRem = len(textRem) + else: + # Maybe add test for line terminators, notably "-" + nextSpace = textRem.find(" ") + if nextSpace < 0: # solid block of text; dump all + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + else: + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + myText0 = textRem[0:oc1].strip() + textRem = textRem[oc1:].strip() + textRem = textRem[oc1:].strip() + charsRem = len(textRem) + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write(srtLine) + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + # + # + # + # + charsRem = 0 + return myLineCount +# + + +# ---------------- MAIN ----------------- + +#outDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #035 A tale of Two architectures/ls035-1/publish" + +inSpeakerDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #040 - Chris Fields... A free energy principle for generic quantum systems/ls040-1_noSpeaker" +inSpeakers = "noSpeaker_ls040-0.Speakers.csv" +inSpeakerDir = "/mnt/d/Documents/FEP-AI/Active Inference Podcast" +inSpeakers = "AllSpeakers.csv" + + +#inSentDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #040 - Chris Fields... A free energy principle for generic quantum systems/ls040-1_noSpeaker" +#inSentFile = "ls036-0_ls036-0.m4a.paragraphs.csv" +#inSentDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #036 Modeling Ourselves/ls036-0" +#inSentFile = "ls036-0_ls036-0.m4a.paragraphs.csv" +#inSentDir = "/mnt/d/Documents/FEP-AI/2022 Org Streams/os003" +#inSentFile = "Bijan_os003-1.m4a.paragraphs.csv" + +charsPerCaption = 40 # cloned from AssemblyAI default - set up override! +#lastMDTs = -1 # initialize last MarkDown timestamp (any possible value is later!) + +#CSV column headers: +# paragraph: start, end, speaker, confid, text +# speakers: VideoLabel, SpeakerLabel, DisplayedSpeakerName, FullSpeakerName, FirstTurn, RangeFrom, RangeTo, Notes + +inSpeakerPath = inSpeakerDir +if inSpeakerPath[-1] != "/": + inSpeakerPath += "/" + +inSpeakerPath += inSpeakers +#docLabel = "ls21-04" +# +#csv_reader = csv.reader(csv_file, delimiter=',') +#csv_reader = csv.DictReader(csv_file) +#csv_reader = csv.DictReader(csv_file, fieldnames = ("VideoLabel", "SpeakerLabel", "DisplayedSpeakerName", "FullSpeakerName", "FirstTurn", "RangeFrom", "RangeTo", "Notes" ), delimiter=',') +#with io.open("file", "r", newline=None) as fd: +with open(inSpeakerPath) as speaker_file: + speaker_reader = csv.reader(speaker_file, delimiter=',') + line_count = 0 + for row in speaker_reader: + if line_count == 0: + print(f'Column names are {", ".join(row)}') + line_count += 1 + else: + rowLen=len(row) + reportString = "" + if rowLen > 2 and row[1] is not None and len(row[1]) > 0: + if row[0] is not None and len(row[0]) > 0: + videoLabel = row[0] + #reportString += "In video " + row[0] + ", " + else: + videoLabel = "" + # + speakerLabel = row[1] + # + if rowLen > 2 and row[2] is not None and len(row[2]) > 0: + displayedName = row[2] + #reportString += "In video " + row[0] + ", " + else: + displayedName = "Speaker " + speakerLabel + # + #reportString += "'" + row[1] + "' stands for '" + row[2] + "'" + if rowLen > 3 and row[3] is not None and len(row[3]) > 0: + fullName = row[3] + else: + fullName = "" + #reportString += " (better known as '" + row[3] + "')" + # + if rowLen > 4 and row[4] is not None and len(row[4]) > 0: + firstTurn = row[4] + else: + firstTurn = "" + #reportString += " after timestamp " + row[5] + # + if rowLen > 5 and row[5] is not None and len(row[5]) > 0: + rangeFrom = row[5] + else: + rangeFrom = "" + # + if rowLen > 6 and row[6] is not None and len(row[6]) > 0: + rangeTo = row[6] + else: + rangeTo = "" + # + if rowLen > 7 and row[7] is not None and len(row[7]) > 0: + notes = row[7] + else: + notes = "" + # + # + if videoLabel == docLabel: # maybe allow defaulting with videoLabel = ''? + speakerDesc[speakerLabel] = {'videoLabel': videoLabel, 'displayedName': displayedName, 'fullName':fullName, 'firstTurn':firstTurn, 'rangeFrom':rangeFrom, 'rangeTo':rangeTo, 'notes':notes} + #print(f'Loaded speaker description {", ".join([videoLabel, speakerLabel, displayedName, fullName, firstTurn, rangeFrom, rangeTo, notes])}') + # + line_count += 1 + +#print(f'Processed {line_count} speaker descriptions.') + +speaker_file.close() + +# -------- paragraphs CSV + +if inSentDir[-1] != "/": + inSentDir += "/" + +inParagPath = inSentDir + inParagFile +#inSentencePath = inParagPath +#inParagPath += inSentFile +#inSentencePath += inSentFile + +#parag_reader = csv.DictReader(parag_file, fieldnames = ("start", "end", "speaker", "confid", "text" )) +#parag_reader = csv.DictReader(parag_file, fieldnames = ("start", "end", "speaker", "confid", "text" ), delimiter='\t') +#parag_reader = csv.reader(parag_file, delimiter=',') + + +rawParags = {} +# deleted following from input +correctedText = "" +firstWordCount = 0 +lastWordCount = 0 + +if outDir[-1] != "/": + outDir += "/" +# + +paragPubPath = outDir + +if paragPubPath[-1] != "/": + paragPubPath += "/" + +paragPubPath += inSentFile + "_paragTranscript.txt" + +#pPubF = open(paragPubPath, "w") + +reportableTime = 0 +parag_count = 0 +paragWordCount = 0 +current_speaker = "(Unknown Speaker)" +#with io.open("file", "r", newline=None) as fd: +parag_file = open(inParagPath, "r", newline=None) +if (parag_file == None): + print(inParagPath + " not found") +else: + allParags = parag_file.readlines() + for pCount, paragRow in enumerate(allParags): + if pCount == 0: + print("Paragraph headers: " + paragRow) + else: + row = paragRow.split('\t') + rowLen = len(row) + #print(row) + #if row[0] is not None and len(row[0]) > 0: + reportString = "" + start = row[0] + #print(start) + #reportString += "Paragraph starts at millisecond " + row[0] + ", " + end = row[1] + #reportString += "ends at " + row[1] + " " + # Whisper extract now inserts paragNum as row[2] + if row[2] is not None and len(row[2]) > 0: + paragNum = row[2] + else: + paragNum = "" + + # + if rowLen > 3 and row[3] is not None and len(row[3]) > 0: + speaker = row[3] + else: + speaker = "" + + # + if rowLen > 4 and row[4] is not None and len(row[4]) > 0: + confid = row[4] + #reportString += ", confidence " + row[3] + " " + else: + confid = "" + + # + if rowLen > 5 and row[5] is not None and len(row[4]) > 0: + startTime = row[5] + #reportString += '"' + row[4].strip('\n') + '"' + else: + startTime = "" + # + if rowLen > 5 and row[5] is not None and len(row[5]) > 0: + text = row[5] + #reportString += '"' + row[5].strip('\n') + '"' + else: + text = "" + # + textLen = len(text) + if rowLen > 6 and row[6] is not None and len(row[6]) > 0: + wordCount = row[6] + #reportString += '"' + row[7].strip('\n') + '"' + else: + wordCount = len(text.split()) + # + # no longer receiving edit-oriented correctedText, firstWordCount, lastWordCount + # + rawParags.update( {start : [end, speaker, confid, firstWordCount, lastWordCount] } ) + # + # + if len(speaker)>0 or len(startTime) > 0 or len(text) > 0 or len(correctedText) > 0: + # Now build next one, two, or three lines of output ([emptyLine] [speaker line] text) + if len(correctedText) > 0: + myText = correctedText + else: + myText = text + # lastBlank = testSrt.rFind(" ") + # + if len(speaker) > 0 and speaker != current_speaker: + #pPubF.write("") # empty line before next speech act + #pPubF.write("\r\n") + reportString = startTime + " " # + speakerIdToName(speaker) + ":" # Also account for missing or illformed start-time + + reportString += speakerIdToName(docLabel, speaker, reportableTime) + ":" + # + #xx=speakerIdToName(docLabel, speaker, reportableTime) + #if len(speaker) == 1: + # reportString += "Speaker " + speaker + ":" # use lookup instead + #else: + # reportString += speaker + ":" + # + # + print(reportString) + #pPubF.write(reportString) + #pPubF.write("\r\n") + current_speaker = speaker + reportString = myText + print(reportString) + #pPubF.write(reportString) + #pPubF.write("\r\n") + else: + #reportString = ToDisplayTime(start) + " " + text + reportString = startTime + " " + myText + print(reportString) + #pPubF.write(reportString) + #pPubF.write("\r\n") + + # + + # + + # + print(f'Processed {pCount} paragraphs.') + +# +parag_file.close() +#pPubF.close() + +print(rawParags) + + +# -------- sentences CSV + +#inSentPath = inSentDir + "/" + inSentFile +inSentPath = inSentDir + inSentFile + +sentPubPath = outDir +srtPubPath = outDir +mDPubPath = outDir + +sentPubPath += inSentFile + "_transcript.txt" +srtPubPath += inSentFile + "_transcript.srt" +mDPubPath += inSentFile + "_transcript.md" + +print("to write-open sentPubPath:") +print(sentPubPath) + +sPubF = open(sentPubPath, "w") +srtPubF = open(srtPubPath, "w") +mDPubF = open(mDPubPath, "w") + +# charsPerCaption limits character length of (brand-new!) SRT file - check above for override logic + +rawSents = {} +accumedParag = "" +accumedSrt = "" +sent_count = 0 +sentWordCount = 0 +lastReportTime = 0 +currentSpeaker = "(Unknown Speaker)" +lastReportTime = 0 + +srtLine = "" +srtLineLen = len(srtLine) +#srtStart = ToSRTTime(srtStartTime) +#srtEnd = ToSRTTime(srtEndTime) +#srtLine = setStart + " --> " +#lastBlank = testSrt.rFind(" ") +""" +>>> a="I am the witch, Doctor!" +>>> print(a.rfind(" ")) +15 +>>> h="abc" +>>> a=h.rfind("b") +>>> print(a) +1 +>>> print(h.rfind("b")) +1 +>>> print(h.rfind("a")) +0 +>>> print(h.rfind("c")) +2 +>>> print(h.rfind("d")) +-1 + +>>> h="aba" +>>> print(h.rfind("a")) +2 +>>> print(h.rfind("b")) +1 +>>> print(h.rfind("c")) +-1 + """ + +paragTimes = rawParags.keys() +print("") +print(paragTimes) +print("") + +print("to read-open inSentPath:") +print(inSentPath) + +#with io.open("file", "r", newline=None) as fd: +sent_file = open(inSentPath, "r", newline=None) +if (sent_file == None): + print(inSentPath + " not found") +else: + allSents = sent_file.readlines() + for pCount, sentRow in enumerate(allSents): + if pCount == 0: + print("Sentence headers: " + sentRow) + else: + row = sentRow.split('\t') + rowLen = len(row) + #print(row) + #if row[0] is not None and len(row[0]) > 0: + reportString = "" + start = int(row[0]) + #print(start) + #reportString += "Sentence starts at millisecond " + row[0] + ", " + end = int(row[1]) + #reportString += "ends at " + row[1] + " " + # Whisper extract now generates sentNum at row[2] + + speechDuration = end - start + + if rowLen > 2 and row[2] is not None and len(row[2]) > 0: + sentNum = row[2] + else: + sentNum = "" + # + if rowLen > 3 and row[3] is not None and len(row[3]) > 0: + speaker = row[3] + else: + speaker = "" + + # + if rowLen > 4 and row[4] is not None and len(row[4]) > 0: + confid = float(row[4]) + #reportString += ", confidence " + row[3] + " " + else: + confid = "" + + # + # dropped textual "startTime" + # + if rowLen > 5 and row[5] is not None and len(row[5]) > 0: + text = row[5].rstrip() + #reportString += '"' + row[5].strip('\n') + '"' + else: + text = "" + # + speechChars = len(text) + + msPerChar = (speechDuration / speechChars) if speechChars > 0 else speechDuration # pretend speech lasts one millisecond! + + # Dropped edit-related columns - RESTORE, maybe! + # + if str(start) in paragTimes: + paragBreak = True + #print(str(start) + " in paragTimes") + else: + paragBreak = False + #print(str(start) + " NOT in paragTimes") + + #if len(speaker)>0 or len(startTime) > 0 or textLen > 0 or len(correctedText) > 0: + srtSpeaker = "" # SRT displays only NEW speaker ID + if len(speaker)>0 or textLen > 0: + # Now build next one, two, or three lines of output ([emptyLine] [speaker line] text) + if len(correctedText) > 0: + myText = correctedText + else: + myText = text + # + if len(speaker) > 0 and speaker != currentSpeaker: + speakerName = speakerIdToName(docLabel, speaker, reportableTime) + srtSpeaker = speakerName + reportableTime = start + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + sPubF.write("") # empty line before next speech act + sPubF.write("\r\n") + #if len(startTime) > 0: + # reportableTime = int(hhMmSsToTime(startTime)) + # reportString = startTime + #else: + reportString = ToDisplayTime(start) + # + #reportString += " " # + speakerIdToName(speaker) + ":" # Also account for missing or illformed start-time + reportString += " " + speakerName + ":" + + #xx=speakerIdToName(docLabel, speaker, reportableTime) + #if len(speaker) == 1: + # reportString += " Speaker " + speaker + ":" # use lookup instead + #else: + # reportString += " " + speaker + ":" + # + print(reportString) + sPubF.write(reportString) + sPubF.write("\r\n") + currentSpeaker = speaker + lastReportTime = reportableTime + reportString = myText + print(reportString) + if len(accumedParag) > 0: + accumedParag += " " + reportString + else: + accumedParag = reportString + # + elif paragBreak: + print("New paragraph per transcription heuristic") + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + reportableTime = start + if (0 + reportableTime) > (60000 + lastReportTime): # Only some 'forced paragraphs' need timestamp + displayTime = ToDisplayTime(start) + reportString = displayTime + " " + lastReportTime = reportableTime + else: + reportString = "" + # + reportString += myText + print(reportString) + #sPubF.write(reportString) + #sPubF.write("\r\n") + if len(accumedParag) > 0: + accumedParag += " " + reportString + else: + accumedParag = reportString + # + if len(accumedSrt) > 0: + accumedSrt += " " + reportString + else: + accumedSrt = reportString + # + else: + #if len(startTime) > 0: + # reportableTime = int(hhMmSsToTime(startTime)) + # print("converted startTime:") + # print(reportableTime) + #else: + reportableTime = start + #print("saved start:") + print(reportableTime) + # + + #print("[typeOf] lastReportTime:") + #print(type(lastReportTime)) + #print(lastReportTime) + #print("[typeOf] reportableTime:") + #print(type(reportableTime)) + #print(reportableTime) + if (0 + reportableTime) > (60000 + lastReportTime): # report time every 60 seconds + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + #if len(startTime) > 0: + # displayTime = startTime + #else: + displayTime = ToDisplayTime(start) + # + reportString = displayTime + " " + lastReportTime = reportableTime + else: + reportString = "" + # + reportString += myText + print(reportString) + #sPubF.write(reportString) + #sPubF.write("\r\n") + if len(accumedParag) > 0: + accumedParag += " " + reportString + else: + accumedParag = reportString + # + if len(accumedSrt) > 0: + accumedSrt += " " + reportString + else: + accumedSrt = reportString + # + # + # + if len(myText) > 0: # SRT written out for each non-empty sentence. + writeToMD(myText, srtPosCount, srtSpeaker, start, end, paragBreak) # pro forma + # use speakername; ignore paragraph info + srtEndTime = end # reminder: take new start as old end + srtPosCount = writeToSrt(text, srtPosCount, srtSpeaker, srtStartTime, srtEndTime) + srtStartTime = start + # + # + # + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + print(f'Processed {pCount} sentences.') + +# +sent_file.close() +sPubF.close() +srtPubF.close() +mDPubF.close() diff --git a/Archive/sentencesToTranscripts_X.py b/Archive/sentencesToTranscripts_X.py new file mode 100644 index 0000000..8ccebb3 --- /dev/null +++ b/Archive/sentencesToTranscripts_X.py @@ -0,0 +1,895 @@ +# +# After "sentencesToTranscripts - Copy (21).py" add SRT-Speaker logic: +# generate fresh SRT *_transcript.srt from *.sentences.csv); insert speaker names formulated from +# +# cd "/mnt/d/Documents/FEP-AI/2022 GuestStream/Mass 2022 GuestStreams" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/sentencesToTranscripts.py" "gs014-1" "." "gs014-1_gs014-1.m4a.sentences.csv" | tee gs014-1.m4a_transcript.json +# +# cd "/mnt/d/Documents/FEP-AI/2022 GuestStream/Mass 2022 GuestStreams" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/sentencesToTranscripts.py" "gs014-1" "." "gs014-1_gs014-1.m4a.sentences.csv" | tee gs014-1.m4a_transcript.json +# +#cd "/mnt/d/Documents/FEP-AI/2022 ModelStream/mo007/SPtest" +# python3 "/mnt/d/Documents/FEP-AI/Active Inference Podcast/sentencesToTranscripts.py" mo007-1 "." "mo007-1_mo007-1.mp3.sentences.csv" | tee mo007-1_publish.txt +# +#AllSpeakers "/mnt/d/Documents/FEP-AI/Active Inference Podcast/AllSpeakers.csv" + +import csv +import time +import sys +import math +import json +from html.parser import HTMLParser + +if __name__ == "__main__": + print(f"Arguments count: {len(sys.argv)}") + if len(sys.argv) == 1: + print("sentencesToTranscripts. Needs parameters docLabel (key binding references to this doc),") + print("inSentDir (path to incoming files), inSentFile (name of driver file *.sentences.csv).") + print("Optional params outDir (defaults to working directory '.'), speakers (defaults to a central CSV identifying all speakers).") + print("Created in outDir: *_transcript.txt, *_built.srt, *_built.xhtml") + print("If inSentDir holds a *.paragraphs.csv file, it's used to force paragraph ends.") + quit() + elif len(sys.argv) < 4: + print("Need at least docLabel, inSentDir, and inSentFile; optional outDir, speakers. Exiting!") + quit() + +#File references: +# inSentDir/inSentFile Driver +# inSpeakerDir/inSpeakers When mappings known +# [inSentDir]/inWords Improves timestamp splitting; optional +# outDir/ One destination for everything +#Parameters: +# charsPerCaption For SRT: Max line len in chars + +charsPerCaption = 40 # cloned from AssemblyAI default - allow override! + +#outDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #035 A tale of Two architectures/ls035-0/publish" + +inSpeakerDir = "/mnt/d/Documents/FEP-AI/Active Inference Podcast/" +inSpeakers = "AllSpeakers.csv" + +docLabel = sys.argv[1] +inSentDir = sys.argv[2] +inSentFile = sys.argv[3] +print("docLabel, inSentDir, inSentFile " + "'" + docLabel + "', '" + inSentDir + "', '" + inSentFile + "'") + +#inSentDir = "/mnt/d/Documents/2022 Org Streams/os003/" +inParagFile = inSentFile.replace('.sentences.', '.paragraphs.') + +if len(sys.argv) > 4: + outDir = sys.argv[4] +else: + outDir = "." #publish to working directory! + +print("outDir: " + "'" + outDir + "'") + +if len(sys.argv) > 5: + speakerFile = sys.argv[5] +else: + speakerFile = "/mnt/d/Documents/FEP-AI/Active Inference Podcast/AllSpeakers.csv" + +print('speakers File: ' + "'" + speakerFile + "'") + +# globals +speakerDesc = {} +srtSpeaker = "" +srtPosCount = 0 +srtStartTime = 0 +srtEndTime = 0 + +srtPubF = "" + +# ++++++ notes ++++++ + +#create new version of "sentencesToTranscripts.py" (of 12/28, 12:48) + +#BUILDING WORD_BOOST LIST + +#Exclude all digit-only.z +#Select all base forms whose first character is always cap as "capitalized" +# Enter all as word_boost +# Enter all single word as spelling +#Decrease the cutoff for number of occurrence, starting with eight, until the next batch will take you over 1000. +#Maybe when you hit that zone, you can exclude "common nouns" and try for a last tranch that keeps you below the largest allowed number of boosts. +# +#prepare to compare to Google/YouTube word list +#confidSentWordList = sentWordVec +#confidSentWordList.sort(reverse=True, key = lambda x: x[3]) # descending by confidence +#print(confidSentWordList) + +#where the fourth component of sentenceWords is confidence, the following gives the highest-confidence words at the top: +#sentenceWords.sort(reverse=True, key = lambda x: x[3]) + +# "Correct Whisper per YouTube (ls038-2).ods" + + +# ----- notes ----- + + + +# ------- Utility functions -------------- + +def hhMmSsToTime(ts): + tsLen = len(ts) + print("in hhMmSsToTime; ts/tsLen:") + print(ts) + print(tsLen) + if tsLen == 8: # hh:mm:ss + hh = int(ts[0:2]) + mm = int(ts[3:5]) + ss = int(ts[6:8]) + to_time= 3600000*hh + 60000*mm + 1000*ss + return to_time + elif tsLen == 7: # h:mm:ss + hh = int(ts[0:1]) + mm = int(ts[2:4]) + ss = int(ts[5:7]) + to_time= 3600000*hh + 60000*mm + 1000*ss + return to_time + elif tsLen == 5: # mm:ss + mm = int(ts[0:2]) + ss = int(ts[3:5]) + to_time= 60000*mm + 1000*ss + return to_time + elif tsLen == 4: # m:ss + mm = int(ts[0:1]) + ss = int(ts[2:4]) + to_time= 60000*mm + 1000*ss + return to_time + else: + return 9999999 + # +# + + + +def ToDisplayTime(tt): + ts=float(0.0+int(tt)) + h0=int(ts/3600000.0) + hh="" + if h0 > 9: + hh = str(100+h0) + hh = hh[1:3] + ":" + elif h0 > 0: + hh = str(h0) + ":" + + m0=int( (ts-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ts - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + to_time= hh + mm[1:3] + ":" + ss[1:3] + return to_time + +#j=ToDisplayTime(64968112) +#print(j) +#j = ToDisplayTime(4968112) +#print(j) +#j = ToDisplayTime(70337) +#print(j) +#j = ToDisplayTime(2337) +#print(j) + + +def ToSRTTime(tt): + ts=float(0.0+int(tt)) + h0=int(ts/3600000.0) + hh = str(100+h0) + m0=int( (ts-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ts - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ts - (3600000.0*h0) - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= hh[1:3] + ":" + mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + +#j=ToSRTTime(64968112) +#print(j) +#j = ToSRTTime(4968112) +#print(j) +#j = ToSRTTime(70337) +#print(j) +#j = ToSRTTime(2337) +#print(j) + +def secToTime(ss): + if ss >= 3600000: + h0=int(ss/3600000.0) + hh = str(100+h0) + m0=int( (ss-(3600000.0*h0))/60000.0) + mm=str(100+m0) + s0=int( (ss - (3600000.0*h0) - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ss - (3600000.0*h0) - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= hh[1:3] + ":" + mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + else: + m0=int( ss / 60000.0) + mm=str(100+m0) + s0=int( (ss - (60000.0*m0) ) /1000.0) + ss=str(100+s0) + mms0=int(ss - (6000*m0) - s0) + mms=str(1000+mms0) + to_time= mm[1:3] + ":" + ss[1:3] + "," + mms[1:4] + return to_time + # +# + + + +# ------- "Business" functions -------------- + +def speakerIdToName(doc, id, myTime): +# Default; override if possible from inSpeakers + #print("ord, len of '" + id) + #print(ord(id)) + #print(len(id)) + if len(id) > 1: # speaker already spelled out in 'sentences' input + return id + # + speaker = "Speaker " + id # default + #print("speakerDesc") + #print(speakerDesc) + spDesc = speakerDesc.get(id) + #print("spDesc") + #print(spDesc) + if spDesc is not None: + dName = spDesc.get('displayedName') + #print("dName") + #print(dName) + if dName is not None and len(dName)>0: + speaker = dName + # + # + return speaker + # +# + + +def writeToSrt(textOut, lineCount, mySpeakerName, startTime, endTime): + print("In writeToSrt, lineCount:") + print(lineCount) + myLineCount = lineCount + if len(mySpeakerName) == 0: + textRem = "" + else: + textRem = mySpeakerName + ": " # We will count length of speaker name as though it were audible. + # This may be convenient for viewing; but it makes + # detailed SRT time-labels useless for reconstructing speech timing + # + textRem += textOut.strip() + charsRem = len(textRem) + timeRem = endTime - startTime + msPerChar = (timeRem / charsRem) if charsRem > 0 else charsRem + oc1 = charsPerCaption+1 # lets us see a single character at end of window + oc2 = oc1 + 1 # sees single character at end of window + #if charsRem > 0: # should try to split last pair of lines evenly + while charsRem > 0: # should try to split last pair of lines evenly + if charsRem <= charsPerCaption: + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write(srtLine) + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + else: + prevSpace = textRem[0:oc2].rfind(" ") + if prevSpace >= 0: # leading integral block of text; dump thru following space + myText0 = textRem[0:prevSpace+1].strip() + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write(srtLine) + srtPubF.write("\r\n") + startTime = endTime + srtPubF.write(myText0) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") # close this SRT block + textRem = textRem[prevSpace:].strip() # remainder + charsRem = len(textRem) + else: + # Maybe add test for line terminators, notably "-" + nextSpace = textRem.find(" ") + if nextSpace < 0: # solid block of text; dump all + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + else: + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + myText0 = textRem[0:oc1].strip() + textRem = textRem[oc1:].strip() + textRem = textRem[oc1:].strip() + charsRem = len(textRem) + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + srtLine = srtStart + " --> " + srtEnd + srtPubF.write(srtLine) + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + # + # + # + # + charsRem = 0 + return myLineCount +# + +""" +def writeToSrt(textOut, lineCount, startTime, endTime): + myLineCount = lineCount + textRem = textOut.strip() + charsRem = len(textRem) + timeRem = endTime - startTime + + if charsRem > 0: + myLineCount += 1 + srtPubF.write(str(myLineCount)) + srtPubF.write("\r\n") + srtStart = ToSRTTime(startTime) + srtEnd = ToSRTTime(endTime) + timeLine = srtStart + " --> " + srtEnd + srtPubF.write(timeLine) + srtPubF.write("\r\n") + srtPubF.write(textRem) + srtPubF.write("\r\n") + srtPubF.write("") + srtPubF.write("\r\n") + charsRem = 0 + # + # + + return myLineCount +""" + +# ---------------- MAIN ----------------- + +#outDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #035 A tale of Two architectures/ls035-1/publish" + +inSpeakerDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #040 - Chris Fields... A free energy principle for generic quantum systems/ls040-1_noSpeaker" +inSpeakers = "noSpeaker_ls040-0.Speakers.csv" +inSpeakerDir = "/mnt/d/Documents/FEP-AI/Active Inference Podcast" +inSpeakers = "AllSpeakers.csv" + + +#inSentDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #040 - Chris Fields... A free energy principle for generic quantum systems/ls040-1_noSpeaker" +#inSentFile = "ls036-0_ls036-0.m4a.paragraphs.csv" +#inSentDir = "/mnt/d/Documents/FEP-AI/2022 Livestreams/ActInf Livestream #036 Modeling Ourselves/ls036-0" +#inSentFile = "ls036-0_ls036-0.m4a.paragraphs.csv" +#inSentDir = "/mnt/d/Documents/FEP-AI/2022 Org Streams/os003" +#inSentFile = "Bijan_os003-1.m4a.paragraphs.csv" + +charsPerCaption = 40 # cloned from AssemblyAI default - set up override! + +#CSV column headers: +# paragraph: start, end, speaker, confid, text +# speakers: VideoLabel, SpeakerLabel, DisplayedSpeakerName, FullSpeakerName, FirstTurn, RangeFrom, RangeTo, Notes + +inSpeakerPath = inSpeakerDir +if inSpeakerPath[-1] != "/": + inSpeakerPath += "/" + +inSpeakerPath += inSpeakers +#docLabel = "ls21-04" +# +#csv_reader = csv.reader(csv_file, delimiter=',') +#csv_reader = csv.DictReader(csv_file) +#csv_reader = csv.DictReader(csv_file, fieldnames = ("VideoLabel", "SpeakerLabel", "DisplayedSpeakerName", "FullSpeakerName", "FirstTurn", "RangeFrom", "RangeTo", "Notes" ), delimiter=',') +#with io.open("file", "r", newline=None) as fd: +with open(inSpeakerPath) as speaker_file: + speaker_reader = csv.reader(speaker_file, delimiter=',') + line_count = 0 + for row in speaker_reader: + if line_count == 0: + print(f'Column names are {", ".join(row)}') + line_count += 1 + else: + rowLen=len(row) + reportString = "" + if rowLen > 2 and row[1] is not None and len(row[1]) > 0: + if row[0] is not None and len(row[0]) > 0: + videoLabel = row[0] + #reportString += "In video " + row[0] + ", " + else: + videoLabel = "" + # + speakerLabel = row[1] + # + if rowLen > 2 and row[2] is not None and len(row[2]) > 0: + displayedName = row[2] + #reportString += "In video " + row[0] + ", " + else: + displayedName = "Speaker " + speakerLabel + # + #reportString += "'" + row[1] + "' stands for '" + row[2] + "'" + if rowLen > 3 and row[3] is not None and len(row[3]) > 0: + fullName = row[3] + else: + fullName = "" + #reportString += " (better known as '" + row[3] + "')" + # + if rowLen > 4 and row[4] is not None and len(row[4]) > 0: + firstTurn = row[4] + else: + firstTurn = "" + #reportString += " after timestamp " + row[5] + # + if rowLen > 5 and row[5] is not None and len(row[5]) > 0: + rangeFrom = row[5] + else: + rangeFrom = "" + # + if rowLen > 6 and row[6] is not None and len(row[6]) > 0: + rangeTo = row[6] + else: + rangeTo = "" + # + if rowLen > 7 and row[7] is not None and len(row[7]) > 0: + notes = row[7] + else: + notes = "" + # + # + if videoLabel == docLabel: # maybe allow defaulting with videoLabel = ''? + speakerDesc[speakerLabel] = {'videoLabel': videoLabel, 'displayedName': displayedName, 'fullName':fullName, 'firstTurn':firstTurn, 'rangeFrom':rangeFrom, 'rangeTo':rangeTo, 'notes':notes} + #print(f'Loaded speaker description {", ".join([videoLabel, speakerLabel, displayedName, fullName, firstTurn, rangeFrom, rangeTo, notes])}') + # + line_count += 1 + +#print(f'Processed {line_count} speaker descriptions.') + +speaker_file.close() + +# -------- paragraphs CSV + +if inSentDir[-1] != "/": + inSentDir += "/" + +inParagPath = inSentDir + inParagFile +#inSentencePath = inParagPath +#inParagPath += inSentFile +#inSentencePath += inSentFile + +#parag_reader = csv.DictReader(parag_file, fieldnames = ("start", "end", "speaker", "confid", "text" )) +#parag_reader = csv.DictReader(parag_file, fieldnames = ("start", "end", "speaker", "confid", "text" ), delimiter='\t') +#parag_reader = csv.reader(parag_file, delimiter=',') + + +rawParags = {} +# deleted following from input +correctedText = "" +firstWordCount = 0 +lastWordCount = 0 + +if outDir[-1] != "/": + outDir += "/" +# + +paragPubPath = outDir + +if paragPubPath[-1] != "/": + paragPubPath += "/" + +paragPubPath += inSentFile + "_paragTranscript.txt" + +pPubF = open(paragPubPath, "w") + +reportableTime = 0 +parag_count = 0 +paragWordCount = 0 +current_speaker = "(Unknown Speaker)" +#with io.open("file", "r", newline=None) as fd: +parag_file = open(inParagPath, "r", newline=None) +if (parag_file == None): + print(inParagPath + " not found") +else: + allParags = parag_file.readlines() + for pCount, paragRow in enumerate(allParags): + if pCount == 0: + print("Paragraph headers: " + paragRow) + else: + row = paragRow.split('\t') + rowLen = len(row) + #print(row) + #if row[0] is not None and len(row[0]) > 0: + reportString = "" + start = row[0] + #print(start) + #reportString += "Paragraph starts at millisecond " + row[0] + ", " + end = row[1] + #reportString += "ends at " + row[1] + " " + # Whisper extract now inserts paragNum as row[2] + if row[2] is not None and len(row[2]) > 0: + paragNum = row[2] + else: + paragNum = "" + + # + if rowLen > 3 and row[3] is not None and len(row[3]) > 0: + speaker = row[3] + else: + speaker = "" + + # + if rowLen > 4 and row[4] is not None and len(row[4]) > 0: + confid = row[4] + #reportString += ", confidence " + row[3] + " " + else: + confid = "" + + # + if rowLen > 5 and row[5] is not None and len(row[4]) > 0: + startTime = row[5] + #reportString += '"' + row[4].strip('\n') + '"' + else: + startTime = "" + # + if rowLen > 5 and row[5] is not None and len(row[5]) > 0: + text = row[5] + #reportString += '"' + row[5].strip('\n') + '"' + else: + text = "" + # + textLen = len(text) + if rowLen > 6 and row[6] is not None and len(row[6]) > 0: + wordCount = row[6] + #reportString += '"' + row[7].strip('\n') + '"' + else: + wordCount = len(text.split()) + # + # no longer receiving edit-oriented correctedText, firstWordCount, lastWordCount + # + rawParags.update( {start : [end, speaker, confid, firstWordCount, lastWordCount] } ) + # + # + if len(speaker)>0 or len(startTime) > 0 or len(text) > 0 or len(correctedText) > 0: + # Now build next one, two, or three lines of output ([emptyLine] [speaker line] text) + if len(correctedText) > 0: + myText = correctedText + else: + myText = text + # lastBlank = testSrt.rFind(" ") + # + if len(speaker) > 0 and speaker != current_speaker: + pPubF.write("") # empty line before next speech act + pPubF.write("\r\n") + reportString = startTime + " " # + speakerIdToName(speaker) + ":" # Also account for missing or illformed start-time + + reportString += speakerIdToName(docLabel, speaker, reportableTime) + ":" + # + #xx=speakerIdToName(docLabel, speaker, reportableTime) + #if len(speaker) == 1: + # reportString += "Speaker " + speaker + ":" # use lookup instead + #else: + # reportString += speaker + ":" + # + # + print(reportString) + pPubF.write(reportString) + pPubF.write("\r\n") + current_speaker = speaker + reportString = myText + print(reportString) + pPubF.write(reportString) + pPubF.write("\r\n") + else: + #reportString = ToDisplayTime(start) + " " + text + reportString = startTime + " " + myText + print(reportString) + pPubF.write(reportString) + pPubF.write("\r\n") + + # + + # + + # + print(f'Processed {pCount} paragraphs.') + +# +parag_file.close() +pPubF.close() + +print(rawParags) + + +# -------- sentences CSV + +#inSentPath = inSentDir + "/" + inSentFile +inSentPath = inSentDir + inSentFile + +sentPubPath = outDir +srtPubPath = outDir + +sentPubPath += inSentFile + "_transcript.txt" +srtPubPath += inSentFile + "_transcript.srt" + +print("to write-open sentPubPath:") +print(sentPubPath) + +sPubF = open(sentPubPath, "w") +srtPubF = open(srtPubPath, "w") +# charsPerCaption limits character length of (brand-new!) SRT file - check above for override logic + +rawSents = {} +accumedParag = "" +accumedSrt = "" +sent_count = 0 +sentWordCount = 0 +lastReportTime = 0 +currentSpeaker = "(Unknown Speaker)" +lastReportTime = 0 + +srtLine = "" +srtLineLen = len(srtLine) +#srtStart = ToSRTTime(srtStartTime) +#srtEnd = ToSRTTime(srtEndTime) +#srtLine = setStart + " --> " +#lastBlank = testSrt.rFind(" ") +""" +>>> a="I am the witch, Doctor!" +>>> print(a.rfind(" ")) +15 +>>> h="abc" +>>> a=h.rfind("b") +>>> print(a) +1 +>>> print(h.rfind("b")) +1 +>>> print(h.rfind("a")) +0 +>>> print(h.rfind("c")) +2 +>>> print(h.rfind("d")) +-1 + +>>> h="aba" +>>> print(h.rfind("a")) +2 +>>> print(h.rfind("b")) +1 +>>> print(h.rfind("c")) +-1 + """ + +paragTimes = rawParags.keys() +print("") +print(paragTimes) +print("") + +print("to read-open inSentPath:") +print(inSentPath) + +#with io.open("file", "r", newline=None) as fd: +sent_file = open(inSentPath, "r", newline=None) +if (sent_file == None): + print(inSentPath + " not found") +else: + allSents = sent_file.readlines() + for pCount, sentRow in enumerate(allSents): + if pCount == 0: + print("Sentence headers: " + sentRow) + else: + row = sentRow.split('\t') + rowLen = len(row) + #print(row) + #if row[0] is not None and len(row[0]) > 0: + reportString = "" + start = int(row[0]) + #print(start) + #reportString += "Sentence starts at millisecond " + row[0] + ", " + end = int(row[1]) + #reportString += "ends at " + row[1] + " " + # Whisper extract now generates sentNum at row[2] + + speechDuration = end - start + + if rowLen > 2 and row[2] is not None and len(row[2]) > 0: + sentNum = row[2] + else: + sentNum = "" + # + if rowLen > 3 and row[3] is not None and len(row[3]) > 0: + speaker = row[3] + else: + speaker = "" + + # + if rowLen > 4 and row[4] is not None and len(row[4]) > 0: + confid = float(row[4]) + #reportString += ", confidence " + row[3] + " " + else: + confid = "" + + # + # dropped textual "startTime" + # + if rowLen > 5 and row[5] is not None and len(row[5]) > 0: + text = row[5].rstrip() + #reportString += '"' + row[5].strip('\n') + '"' + else: + text = "" + # + speechChars = len(text) + + msPerChar = (speechDuration / speechChars) if speechChars > 0 else speechDuration # pretend speech lasts one millisecond! + + # Dropped edit-related columns - RESTORE, maybe! + # + if str(start) in paragTimes: + paragBreak = True + #print(str(start) + " in paragTimes") + else: + paragBreak = False + #print(str(start) + " NOT in paragTimes") + + #if len(speaker)>0 or len(startTime) > 0 or textLen > 0 or len(correctedText) > 0: + srtSpeaker = "" # SRT displays only NEW speaker ID + if len(speaker)>0 or textLen > 0: + # Now build next one, two, or three lines of output ([emptyLine] [speaker line] text) + if len(correctedText) > 0: + myText = correctedText + else: + myText = text + # + if len(speaker) > 0 and speaker != currentSpeaker: + speakerName = speakerIdToName(docLabel, speaker, reportableTime) + srtSpeaker = speakerName + reportableTime = start + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + sPubF.write("") # empty line before next speech act + sPubF.write("\r\n") + #if len(startTime) > 0: + # reportableTime = int(hhMmSsToTime(startTime)) + # reportString = startTime + #else: + reportString = ToDisplayTime(start) + # + #reportString += " " # + speakerIdToName(speaker) + ":" # Also account for missing or illformed start-time + reportString += " " + speakerName + ":" + + #xx=speakerIdToName(docLabel, speaker, reportableTime) + #if len(speaker) == 1: + # reportString += " Speaker " + speaker + ":" # use lookup instead + #else: + # reportString += " " + speaker + ":" + # + print(reportString) + sPubF.write(reportString) + sPubF.write("\r\n") + currentSpeaker = speaker + lastReportTime = reportableTime + reportString = myText + print(reportString) + if len(accumedParag) > 0: + accumedParag += " " + reportString + else: + accumedParag = reportString + # + elif paragBreak: + print("New paragraph per transcription heuristic") + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + reportableTime = start + if (0 + reportableTime) > (60000 + lastReportTime): # Only some 'forced paragraphs' need timestamp + displayTime = ToDisplayTime(start) + reportString = displayTime + " " + lastReportTime = reportableTime + else: + reportString = "" + # + reportString += myText + print(reportString) + #sPubF.write(reportString) + #sPubF.write("\r\n") + if len(accumedParag) > 0: + accumedParag += " " + reportString + else: + accumedParag = reportString + # + if len(accumedSrt) > 0: + accumedSrt += " " + reportString + else: + accumedSrt = reportString + # + else: + #if len(startTime) > 0: + # reportableTime = int(hhMmSsToTime(startTime)) + # print("converted startTime:") + # print(reportableTime) + #else: + reportableTime = start + #print("saved start:") + print(reportableTime) + # + + #print("[typeOf] lastReportTime:") + #print(type(lastReportTime)) + #print(lastReportTime) + #print("[typeOf] reportableTime:") + #print(type(reportableTime)) + #print(reportableTime) + if (0 + reportableTime) > (60000 + lastReportTime): # report time every 60 seconds + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + #if len(startTime) > 0: + # displayTime = startTime + #else: + displayTime = ToDisplayTime(start) + # + reportString = displayTime + " " + lastReportTime = reportableTime + else: + reportString = "" + # + reportString += myText + print(reportString) + #sPubF.write(reportString) + #sPubF.write("\r\n") + if len(accumedParag) > 0: + accumedParag += " " + reportString + else: + accumedParag = reportString + # + if len(accumedSrt) > 0: + accumedSrt += " " + reportString + else: + accumedSrt = reportString + # + # + # + if textLen > 0: # SRT written out for each non-empty sentence. + # use speakername; ignore paragraph info + srtEndTime = end # reminder: take new start as old end + srtPosCount = writeToSrt(text, srtPosCount, srtSpeaker, srtStartTime, srtEndTime) + srtStartTime = start + # + # + # + if len(accumedParag) > 0: + sPubF.write(accumedParag) + sPubF.write("\r\n") + accumedParag = "" + # + print(f'Processed {pCount} sentences.') + +# +sent_file.close() +sPubF.close() +srtPubF.close()