{"id":1280,"date":"2023-05-20T22:40:15","date_gmt":"2023-05-20T22:40:15","guid":{"rendered":"http:\/\/wp.chaoyu.nl\/?p=1280"},"modified":"2024-03-26T22:14:04","modified_gmt":"2024-03-26T21:14:04","slug":"project-notes-whisper-apex-python-learn-dutch-app","status":"publish","type":"post","link":"https:\/\/chaoyu.nl\/?p=1280","title":{"rendered":"Project Notes: Whisper + APEX + Python+React+ LEARN DUTCH APP"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">here is the semi finished outcome. <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/learn.chaoyu.nl\/\">https:\/\/learn.chaoyu.nl\/<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"1920\" style=\"aspect-ratio: 888 \/ 1920;\" width=\"888\" controls src=\"http:\/\/wp.chaoyu.nl\/wp-content\/uploads\/2023\/05\/RPReplay_Final1709231871.mp4\"><\/video><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"790\" height=\"576\" src=\"http:\/\/wp.chaoyu.nl\/wp-content\/uploads\/2023\/05\/Screenshot-from-2023-05-21-00-40-49.png\" alt=\"\" class=\"wp-image-1282\" style=\"width:846px;height:617px\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><em>The Why: I am learning Dutch, I listen to a lot of BNR news on my 2.5 to 3 hours drive from home to office and back. I feel like that I understand a lot of the content but at same time miss a lot of the context. I really wanna have a transcript of the podcast so I can read and listen at the same time. <\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>The What: Ideally a Mobile App that I can use to note words, linking words from these audios and play the sentences where the words are used. more .. and more .. <\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>The How: a lot of patience<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>On Ubuntu Whisper Server<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Miniconda, TensorFlow, Pytorch, Nvidia gtx 1080ti<\/li>\n\n\n\n<li>OCI CLI<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Python Codes<\/strong><\/p>\n\n\n\n<p class=\"has-light-green-cyan-background-color has-background has-small-font-size wp-block-paragraph\"><strong>getListofAudiosToTranscript.py<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code lang=\"python\" class=\"language-python line-numbers\">import requests\nfrom oauthlib.oauth2 import BackendApplicationClient\nfrom requests_oauthlib import OAuth2Session\nimport os\n\n\nclient_id = \"\"\nclient_secret = \"\"\ntoken_url = \"https:\/\/apex.chaoyu.nl\/ords\/dev_apex\/oauth\/token\" \n\n\n# Create an OAuth2 session\nclient = BackendApplicationClient(client_id=client_id)\noauth = OAuth2Session(client=client)\ntoken = oauth.fetch_token(token_url=token_url, client_id=client_id, client_secret=client_secret)\n\n# Make a REST call with OAuth2 authentication\nurl = 'https:\/\/apex.chaoyu.nl\/ords\/dev_apex\/learndutchforfree\/listfilestocreatetranscripts'  # Replace with your API endpoint\n\nresponse = oauth.get(url)\n\nif response.status_code == 200:\n    data = response.json()  # If the response contains JSON data\n    # print(data)\n    for items in data:\n        print(items['audio_name'])\n        cmd = \"oci os object get -bn public --name \"+items['audio_name']+ \" --file .\/AudioFilesToProcess\/\" + items['audio_name']+ \" --no-multipart\"\n        os.system(cmd)\n\n    os.system('conda run -n tf python transcriptAudios.py') # I activate the conda environment tf (tensorflow) and run the python script\n    \nelse:\n    print(\"Error:\", response.status_code)<\/code><\/pre>\n\n\n\n<p class=\"has-light-green-cyan-background-color has-background has-small-font-size wp-block-paragraph\"><strong>transcriptAudios.py<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code lang=\"python\" class=\"language-python line-numbers\">import whisper\n# import required module\nimport os\nimport torch\n# assign directory\ndirectory = '.\/AudioFilesToProcess\/'\nmodel = whisper.load_model(\"large\")\n\nfor filename in os.listdir(directory):\n    torch.cuda.empty_cache()\n\n    result = model.transcribe(directory+filename)\n\n    clobText = ''\n    for items in result[\"segments\"]:\n        clobText += ' {\"Id\":\"' + str(items[\"id\"]) + '\",\"starts\":\"' + str(round(items[\"start\"], 2)) + '\",\"text\":\"' + items[\"text\"] + \"\\\"}\\n\" \n    # print(clobText)\n    from updateTranscriptColumn import updateTranscriptColumn\n    updateTranscriptColumn(filename, clobText)\n\nfor filename in os.listdir(directory):\n    os.remove(directory+filename)<\/code><\/pre>\n\n\n\n<p class=\"has-light-green-cyan-background-color has-background has-small-font-size wp-block-paragraph\"><strong>updateTranscriptColumn.py<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code lang=\"python\" class=\"language-python line-numbers\">import requests\nfrom oauthlib.oauth2 import BackendApplicationClient\nfrom requests_oauthlib import OAuth2Session\nimport json\n\n# OAuth2 client credentials\nclient_id = \"\"\nclient_secret = \"\"\ntoken_url = \"https:\/\/apex.chaoyu.nl\/ords\/dev_apex\/oauth\/token\" \n\n# Create an OAuth2 session\nclient = BackendApplicationClient(client_id=client_id)\noauth = OAuth2Session(client=client)\ntoken = oauth.fetch_token(token_url=token_url, client_id=client_id, client_secret=client_secret)\n\n# Make a POST REST call with OAuth2 authentication and JSON data\nurl = 'https:\/\/apex.chaoyu.nl\/ords\/dev_apex\/learndutchforfree\/uploadtranscript'   # Replace with your API endpoint\n\n\ndef updateTranscriptColumn(audio_name, transcript):\n    data = {\n        \"file_name\": audio_name,\n        \"transcript\": transcript\n    }\n    headers = {\n        'Content-Type': 'application\/json'\n    }\n    # print(json.dumps(data))\n    response = oauth.post(url, data=json.dumps(data), headers=headers)\n\n    if response.status_code == 200:\n        result = response.json()  # If the response contains JSON data\n        print(result)\n    else:\n        result = response.json()\n        print(\"Error:\", response.status_code)\n        print(\"Error:\", result)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>On APEX<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code lang=\"sql\" class=\"language-sql line-numbers\">create or replace package ldff_utility_pck is\n\n   -- Author  : CHAOY\n   -- Created : 19\/05\/2023 21:39:38\n   -- Purpose : \n\n   procedure pr_ajax_fileuploadhandler;\n\n   procedure pr_insert_audio(i_audio_name in audios_ldff.audio_name%type\n                            ,i_mime       in audios_ldff.audio_mime%type\n                            ,i_blob       in audios_ldff.file_content%type);\n\n   procedure pr_oci_file_upload(i_file_name in audios_ldff.audio_name%type\n                               ,i_blob      in audios_ldff.file_content%type\n                               ,i_mime      in audios_ldff.audio_mime%type);\n\n   procedure pr_list_files_for_transcripts;\n\n   procedure pr_post_req_audio_transcript(i_requst_body in blob);\n\n   function fn_return_audio_html(i_file_name in audios_ldff.audio_name%type) return clob;\n\nend ldff_utility_pck;\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:12px\"><code lang=\"sql\" class=\"language-sql line-numbers\">create or replace package body ldff_utility_pck is\n\n   c_oci_base_url         constant varchar2(100) := 'https:\/\/objectstorage.eu-frankfurt-1.oraclecloud.com';\n   c_oci_bucket_namespace constant varchar2(100) := '\/n\/frpnibrn7ulj';\n   c_oci_bucket_name      constant varchar2(100) := '\/b\/public\/o\/';\n   c_oci_auth             constant varchar2(10) := 'OCI_AUTH';\n\n   procedure pr_ajax_fileuploadhandler is\n   \n      l_collection_name constant apex_collections.collection_name%type := 'AJAX_FILE_UPLOADED';\n      l_blob        blob;\n      l_filename    varchar2(200);\n      l_mime_type   varchar2(200);\n      l_multi_parts varchar2(32000);\n      l_count       number;\n      e_exits       exception;\n   begin\n      l_filename  := apex_application.g_x01;\n      l_mime_type := nvl(apex_application.g_x02\n                        ,'application\/octet-stream');\n   \n      -- build BLOB from f01 30k array (base64 encoded)\n      dbms_lob.createtemporary(l_blob\n                              ,false\n                              ,dbms_lob.session);\n   \n      for i in 1 .. apex_application.g_f01.count\n      loop\n         l_multi_parts := wwv_flow.g_f01(i);\n         if length(l_multi_parts) &gt; 0\n         then\n            dbms_lob.append(dest_lob =&gt; l_blob\n                           ,src_lob  =&gt; to_blob(utl_encode.base64_decode(utl_raw.cast_to_raw(l_multi_parts))));\n         end if;\n      end loop;\n   \n      apex_collection.create_or_truncate_collection(p_collection_name =&gt; l_collection_name);\n      -- add collection member (only if BLOB is not null)\n      if dbms_lob.getlength(l_blob) is not null\n      then\n         select count(1)\n         into   l_count\n         from   audios_ldff t\n         where  t.audio_name = l_filename;\n      \n         if l_count &lt;&gt; 0\n         then\n            raise e_exits;\n         end if;\n      \n         pr_insert_audio(i_audio_name =&gt; l_filename\n                        ,i_mime       =&gt; l_mime_type\n                        ,i_blob       =&gt; l_blob);\n      \n         pr_oci_file_upload(i_file_name =&gt; l_filename\n                           ,i_blob      =&gt; l_blob\n                           ,i_mime      =&gt; l_mime_type);\n         \/*\n         apex_collection.add_member(p_collection_name =&gt; l_collection_name\n                                   ,p_c001            =&gt; l_filename\n                                   ,p_c002            =&gt; l_mime_type\n                                   ,p_blob001         =&gt; l_blob);\n                                   \n                                   *\/\n      end if;\n   \n      apex_json.open_object;\n      apex_json.write(p_name  =&gt; 'result'\n                     ,p_value =&gt; 'success');\n      apex_json.close_object;\n   \n   exception\n      when e_exits then\n         apex_json.open_object;\n         apex_json.write(p_name  =&gt; 'result'\n                        ,p_value =&gt; 'fail');\n         apex_json.write(p_name  =&gt; 'errormsg'\n                        ,p_value =&gt; 'File name taken');\n         apex_json.close_object;\n      when others then\n         apex_json.open_object;\n         apex_json.write(p_name  =&gt; 'result'\n                        ,p_value =&gt; 'fail');\n         apex_json.write(p_name  =&gt; 'errormsg'\n                        ,p_value =&gt; sqlerrm);\n         apex_json.close_object;\n   end pr_ajax_fileuploadhandler;\n\n   procedure pr_insert_audio(i_audio_name in audios_ldff.audio_name%type\n                            ,i_mime       in audios_ldff.audio_mime%type\n                            ,i_blob       in audios_ldff.file_content%type) is\n   begin\n   \n      insert into audios_ldff\n         (audio_name\n         ,audio_mime\n          --,file_content\n         ,file_size)\n      values\n         (i_audio_name\n         ,i_mime\n          --,i_blob\n         ,round(dbms_lob.getlength(i_blob) \/ 1024 \/ 1024));\n   \n      ---\n   \n   end pr_insert_audio;\n\n   procedure pr_oci_file_upload(i_file_name in audios_ldff.audio_name%type\n                               ,i_blob      in audios_ldff.file_content%type\n                               ,i_mime      in audios_ldff.audio_mime%type) is\n   \n      l_response clob;\n   begin\n      apex_web_service.g_request_headers(1).name := 'Content-Type';\n      apex_web_service.g_request_headers(1).value := i_mime;\n   \n      l_response := apex_web_service.make_rest_request(p_url                  =&gt; c_oci_base_url ||\n                                                                                 c_oci_bucket_namespace ||\n                                                                                 c_oci_bucket_name || i_file_name\n                                                      ,p_http_method          =&gt; 'PUT'\n                                                      ,p_body_blob            =&gt; i_blob\n                                                      ,p_credential_static_id =&gt; c_oci_auth);\n   \n   end pr_oci_file_upload;\n   ---\n   procedure pr_list_files_for_transcripts is\n      c_audios sys_refcursor;\n   \n   begin\n      \/*\n         open c_audios for\n            select t.audio_name\n            from   audios_ldff t\n            where  t.audio_transcript is null;\n         apex_json.write('data'\n                        ,rec.audio_name);\n      *\/\n      apex_json.open_array;\n   \n      for rec in (select t.audio_name\n                  from   audios_ldff t\n                  where  t.audio_transcript is null)\n      loop\n         apex_json.open_object;\n         apex_json.write('audio_name'\n                        ,rec.audio_name);\n         apex_json.close_object; \n      end loop;\n      apex_json.close_all;\n   \n   end pr_list_files_for_transcripts;\n\n   ---------\n\n   procedure pr_post_req_audio_transcript(i_requst_body in blob) is\n   \n      l_json_object json_object_t;\n      l_file_name   audios_ldff.audio_name%type;\n      l_transcript  audios_ldff.audio_transcript%type;\n   begin\n      l_json_object := json_object_t.parse(i_requst_body);\n      l_file_name   := l_json_object.get_string(key =&gt; 'file_name');\n      l_transcript  := l_json_object.get_clob(key =&gt; 'transcript');\n   \n      update audios_ldff t\n      set    t.audio_transcript = l_transcript\n      where  t.audio_name = l_file_name;\n   \n      apex_json.open_object;\n      apex_json.write(p_name  =&gt; 'result'\n                     ,p_value =&gt; 'success');\n      apex_json.write(p_name  =&gt; 'file_name'\n                     ,p_value =&gt; l_file_name);\n      apex_json.write(p_name  =&gt; 'transcripsSize'\n                     ,p_value =&gt; length(l_transcript));\n      apex_json.close_object;\n   \n   exception\n      when others then\n         apex_json.open_object;\n         apex_json.write(p_name  =&gt; 'result'\n                        ,p_value =&gt; 'fail');\n         apex_json.write(p_name  =&gt; 'errormsg'\n                        ,p_value =&gt; sqlerrm);\n         apex_json.close_object;\n      \n   end pr_post_req_audio_transcript;\n\n   -------\n   function fn_return_audio_html(i_file_name in audios_ldff.audio_name%type) return clob is\n      l_json_payload clob;\n      l_response     clob;\n   \n      l_base_url         constant varchar2(100) := 'https:\/\/objectstorage.eu-frankfurt-1.oraclecloud.com';\n      l_bucket_namespace constant varchar2(100) := '\/n\/frpnibrn7ulj\/b\/public';\n      l_json_obj json_object_t;\n   \n   begin\n      apex_json.initialize_clob_output(p_preserve =&gt; true);\n      apex_json.open_object;\n      apex_json.write('accessType'\n                     ,'ObjectRead');\n      apex_json.write('name'\n                     ,'myRequest' || to_char(systimestamp at time zone 'UTC'\n                                            ,'yyyyddmmhh24miss')); -- required, but arbitrary. must be unqiue\n      apex_json.write('objectName'\n                     ,i_file_name); -- required if access type is ObjectRead, Duhhhhh..\n   \n      apex_json.write('timeExpires'\n                     ,to_char(systimestamp at time zone 'UTC' + numtodsinterval(1\n                                                     ,'HOUR')\n                             ,'yyyy-mm-dd\"T\"hh24:mi:ss\"Z\"')); -- required,  why UTC, because OCI works UTC. What is T and Z, T is just a sperator where Z is UTC 0 ( PAR expiration must conform to RFC 3339: 2023-05-2000:42:59)\n      apex_json.close_object;\n      l_json_payload := apex_json.get_clob_output;\n      l_response     := apex_web_service.make_rest_request(p_url                  =&gt; l_base_url || l_bucket_namespace ||\n                                                                                     '\/p\/'\n                                                          ,p_http_method          =&gt; 'POST'\n                                                          ,p_body                 =&gt; l_json_payload\n                                                          ,p_credential_static_id =&gt; 'OCI_AUTH');\n   \n      l_json_obj := json_object_t.parse(l_response);\n   \n      if apex_web_service.g_status_code = 200\n      then\n         return '&lt;audio controls id=\"p5-audio-player\" autoplay&gt; ' || '&lt;source src=\"' || l_base_url || l_json_obj.get_string('accessUri') || '\" type=\"audio\/mp3\"&gt;Your browser does not support the audio element.&lt;\/audio&gt;';\n      end if;\n   \n      return '&lt;span&gt;Error&lt;\/span&gt;';\n   exception\n      when others then\n         return '&lt;span&gt;Error&lt;\/span&gt;';\n   end fn_return_audio_html;\nend ldff_utility_pck;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>here is the semi finished outcome. https:\/\/learn.chaoyu.nl\/ The Why: I am learning Dutch, I listen to a lot of BNR news on my 2.5 to 3 hours drive from home to office and back. I feel like that I understand a lot of the content but at same time miss a lot of the context&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":1282,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[56,54,55,1],"tags":[],"class_list":["post-1280","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-chatgpt","category-docker","category-python","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/posts\/1280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1280"}],"version-history":[{"count":15,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/posts\/1280\/revisions"}],"predecessor-version":[{"id":1602,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/posts\/1280\/revisions\/1602"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=\/wp\/v2\/media\/1282"}],"wp:attachment":[{"href":"https:\/\/chaoyu.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chaoyu.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}