@אסטרונאוט אני לא חושב שיש שם משהו מסובך.
אולי הממשק לא כ"כ נוח אבל די פשוט.
אתה נכנס לקישור שהבאתי ויש לך למטה מקום לכתוב הנחיה ולעלות קבצים מהמחשב ואז יש לך לשלוח את זה ולקבל את התוצאה.
כבוד הרב
-
בירור | תמלול הקלטות לעברית - בדיוק מלא -
בירור | תמלול הקלטות לעברית - בדיוק מלא@אסטרונאוט יותר מג'מני סטודיו?
-
בירור | בינה מלאכותית שאפשר לאמן/להכניס טקסט ויש לה APIהאם יש בינה מלאכותית שאפשר לאמן או להכניס לה טקסט (ותהיה צמודה אליו, ורק אליו, בלי >סטיות כלל) ויש לה API שנותן לשלוח בקשות ולקבל תשובות?
לצורך יצירת בוט טלפוני עסקי.
לכן חשוב שהוא ישתמש אך ורק בחומר שנתנו לו ולא יבלבלו אותו או ינצלו אותו לדברים אחרים.
יש לי קצת ניסיון בתחום.
לדעתי אם יש לך עד 150 טקסטים קבועים פשוט תיצור 150 שלוחות שכל אחת משמיע טקסט אחר ואז אתה כותב לג'מני אינדקס של תמצית של כל שלוחה ומה מספר השלוחה ומבקש ממנו להחזיר את מספר השלוחה התואם בלבד ואז כמובן עם זה אתה מפנה את הלקוח לשלוחה הרצויה.
אם מדובר על הרבה יותר מזה אז אני גם ניסיתי עם גמני 3 פלש עם הטמעה והוא עובד כמעט ב-100% בציטוט מדוייק אתה יכול לנסות למצא את הטקסט שאליו הוא התכוון עם חיפוש מקורב.
אני הגעתי איתו מתוך מאגרים ענקיים לתוצאות מושלמות. -
בירור | מה זה הקלוד קוד שנכנס לחיינו ביום בהיר@למה-באתי כן צריך מנוי פרו ב-20$ לחודש.
או שאתה רוצה ב-API לשלם לפי שימוש.
כפי שאתה רואה. -
בירור | תמלול הקלטות לעברית - בדיוק מלא@לעזור-לכולם לדעתי הכי מדויק זה ג'מני 3 פרו יש לך אותו כאן בחינם לבדיקות.
אתה יכול להגיד לו בדיוק איך אתה רוצה את הנתונים וכו' וכמובן יש לו גם API תיעוד כאן. -
המלצה | ממשק פניות למוקדי תמיכה שמסתנכרן עם ג'מייל.@דוד-ארן אני לא מצאתי משהו יותר טוב במחיר כזה.
אם מצאת אדרבה תמליץ לי אם כי לא חסר לי שם כלום ואני יכול לעשות שם הכל.
שים לב שזה יותר ניהול מערכת פניות אין שם ניהול מכירות וכד' -
המלצה | ממשק פניות למוקדי תמיכה שמסתנכרן עם ג'מייל.@דוד-ארן זה ממשק במקום ג'מייל הוא מושך משם את המיילים.
זה בעברית מלאה תורגם על ידי והוכנס רשמית לספריה -
המלצה | ממשק פניות למוקדי תמיכה שמסתנכרן עם ג'מייל.שלום וברכה.
חיפשתי המון זמן איך אפשר בקלות להפוך חשבון ג'מייל רגיל לממשק לניהול פניות (CRM).
לפני כמה חודשים מצאתי את מבוקשי freescout.net זה ממשק שמתחבר גם לג'מייל ודרכו אפשר לנהל נציגים לראות מה כל אחד ענה ולהקצות משימות לנציגים ולדעתי בעצם כמעט כל מה שצריך כדי להקים מערך פניות מקצועי כלל גישה ב-API התמשקות עם ווצאפ' ועוד המון פונקציות.
הספריה עצמה היא בחינם אם כי התוספים שלה הרשמים עולים כסף (אני שילמתי פחות מ-1,000 ש"ח חד פעמי לכל התוספים שהייתי צריך ולא מאמין שמישהו צריך יותר מזה) כמובן שצריך שרת בשביל זה (אם אתם רוצים שרת במיוחד בשביל זה יש כאן זולים).
אני אישית משתמש עם זה כבר כמה חודשים טובים למאות פניות ביום ואני מאוד מרוצה מזה.
הם גם מפתחים את זה כל הזמן בלי הפסקה וכל מה שביקשתי מהם הם הוסיפו תוך זמן קצר מאוד!
ממליץ בחום לכל מי שיש לו ארגון קצת גדול וכל המייל שלו נהיה בלאגן אחד גדול. -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@מתכנת-חובב
לגבי המרת Base64 מול בינארי:
אתה צודק ש-Base64 מוסיף תקורה של כ-33% וזה לא יעיל.
פשוט מסיבה פרקטית שאיך שאני משתמש עכשי בתוכנה זה עובד רק עם הדבקה של טקסט ורק ככה אפשר לשלוח קובץ בימארי בטקסט.
לגבי WEFAX:
נכון, זה פרוטוקול עתיק ואיטי. היתרון היחיד שלו הוא שהוא ויזואלי וסלחן לשגיאות. אם יש קטיעה בשידור, אתה מקבל פס שחור קטן בתמונה אבל שאר התמונה ממשיכה להגיע. בהעברת קובץ ZIP, ביט אחד שגוי והקובץ מושחת. למשתמש הפשוט שרוצה להעביר מסמך קריא, לפעמים הויזואליות עדיפה על היעילות.בכל אופן הגישה שלי היא למצא משהו בנוי שכבר תואם לדרישות שלי ואחרי שאני ימצא את הכלי המדויק אולי ננסה לחכות אותו, ואני משער שזה אפשרי לשנות את הפרויקט כאן ולהתאים אותו לצרכים המלאים.
או שאולי פשוט לעשות לו ממשק דרך הדפדפן (בדקתי וזה עובד). -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@מתכנת-חובב ממה שאני בדקתי וניסיתי המודל המהיר ביותר שתפס טוב זה היה
BPSK-250שהוא ממש מהיר משמעותית מכל מה שבדקתי עד עכשיו והוא עבד מעולה כמעט ללא שגיאות, לדעתי זה פשוט צלילים שפחות מסוננים בחברות תקשורת.
יש לציין שעדיין לא הצלחתי לחבר את הטלפון עם כבל אוקס למחשב ושהמחשב יקלוט אותו אני משער שאם הייתי מצליח הייתי יכול אפילו להשתמש ביותר מהירים.
כמו כן יש לציין שזה עבד לי רק כשהיה לי דור 4 ברמה יציבה בדור שלוש זה פשוט לא עבד.
יצרתי גם סקריפט להמרת קובץ לפורמט טוב לתוכנה:
Drag_To_Encode.bat
גוררים על זה קובץ והוא מעתיק אוטמטית את הטקסט להדבקה בתוכנה.
וסקריפט להמרה בחזרה מהתוכנה:
Paste_To_File.bat
פותחים את הסקריפט לוחצים על כל מקש במקלדת ואז נפתח חלון של פנקס רשימות מדביקים בו את התוצאה של ההמרה של הצליל מהתוכנה ואז שומרים וסוגרים את החלון של פנקס רשימות ואז צריך להקליד שם לשמירה (כולל סיומת) והקובץ נשמר.
כמו כן יש פרוטוקול מיוחד לתמונות שהוא עובר שורה שורה ומדפיס אותה וגם אם התפשל שורה אחת השורה הבאה יכולה לצאת טובה קוראים לוWEFAX-IOS288(כמדומני ש-WEFAX-IOS576לא עבד טוב עם ימות המשיח) מגעים לממשק של שליחת תמונה ככה:View>Weather Fax Image TX. -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלאמי שרוצה לראות תוצאות ומהירות בשטח.
יש לבחור בפרוטוקול MFSK32 (בהודעה הקודמת כתוב איך לעשות את זה לגבי MT63-2000L).
להתקשר לקו שמספרו: 0794946346 להפעיל על רמקול לא מדאי חזק אבל שיהיה קרוב למיקרופון ותראו את התוצאות בחלון הצהוב של התוכנה הנ"ל. -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלאטוב מצאתי לזה תוכנה שיש שם את האופציה הזו מובנית שפחות או יותר לזה היא נוצרה (בשביל אנשים שמנותקים מהעולם).
לפרטים נוספים על התוכנה עיין כאן.
בכל אופן לא היה לי זמן וראש לכתוב לזה מדריך אז כתבתי לג'מיני שיכתוב לי לזה מדריך, זה לא יצא משהו אבל סביר, צריך עוד הרבה חוש תכני כדי להבין מה צריך לעשות ואיך.
בכל אופן צריך לשבת על זה ולבדוק מה באמת הפרוטוקול הטוב ביותר שלא מדאי רגיש וקולט כל נשימה ולא מדי גס שלא קולט הכל.
אשמח אם מישהו יוכל לעשות את זה לטובת הכלל כי נראה לי שדרך זה הגענו ליעד!@מתכנת-חובב לדעתי תהנה מהתוכנה הזו.
מדריך מלא: העברת קבצים למחשב מנותק (Offline) דרך קו טלפון
באמצעות מערכת "ימות המשיח" ותוכנת Fldigi
מדריך זה מסביר כיצד להעביר קבצים (EXE, PDF, תמונות, סקריפטים) למחשב מנותק מרשת, על ידי המרת הקובץ לצלילים העמידים בפני הפרעות קו טלפון.
רשימת ציוד נדרש
- מחשב שולח (מחובר): להכנת הקובץ.
- מחשב מקבל (מנותק): אליו נעביר את המידע.
- תוכנת Fldigi: להורדה מכאן (SourceForge).
- מיקרופון: מחובר למחשב המנותק (או כבל AUX).
שלב א': התקנה והגדרות ראשוניות (חובה בשני המחשבים)
לאחר התקנת התוכנה והפעלתה בפעם הראשונה, יפתח "אשף ההגדרות". יש לפעול בדיוק לפי השלבים הבאים:
- מסך 1 (Welcome): לחץ Next.
- מסך 2 (Operator Info):
- מלא פרטים פיקטיביים (למשל:
TESTב-Callsign, ו-USERב-Name). - זה לא משנה לשימוש שלנו. לחץ Next.
- מלא פרטים פיקטיביים (למשל:
- מסך 3 (Audio Devices) - המסך הכי חשוב!
- סמן את האפשרות PortAudio.
- Capture: בחר את המיקרופון שדרכו תקלוט את הצלילים.
- Playback: בחר את הרמקולים של המחשב.
- חשוב מאוד: וודא שהתיבה "File I/O only" אינה מסומנת (ריקה). אם היא מסומנת, לא תוכל לייצר קבצי שמע.
- לחץ Next.
- מסכים 4, 5, 6 (Rig Control - Flrig/RigCAT/Hamlib):
- אל תיגע בכלום. מסכים אלו מיועדים למכשירי קשר פיזיים.
- פשוט לחץ Next שוב ושוב עד שתעבור אותם.
- מסכים 7, 8 (Updates/Web):
- לחץ Finish.
שלב ב': הכנת הקובץ לשידור (במחשב השולח)
מכיוון שהמודם משדר טקסט, עלינו להמיר את הקובץ הבינארי לטקסט.
-
המרת הקובץ לטקסט:
- פתח שורת פקודה (CMD) בתיקייה שבה נמצא הקובץ.
- הקלד:
certutil -encode file.pdf data.txt(החלף אתfile.pdfבשם הקובץ שלך). - פתח את
data.txtוהעתק את כל תוכנו (כולל השורותBEGIN CERTIFICATE).
-
המרת הטקסט לקובץ שמע (WAV) ב-Fldigi:
- פתח את Fldigi.
- בחר פרוטוקול עמיד לרעשים:
Op Mode>MT63>MT63-2000L. - הדבק את הטקסט שהעתקת בחלון התכלת (התחתון).
- בתפריט:
File>Audio>TX Generate. - שמור את הקובץ בשם
000.wav. - אינדיקציה: הטקסט בחלון התכלת ישנה צבע במהירות – סימן שהקובץ נוצר.
שלב ג': העלאה למערכת "ימות המשיח"
- כנס לממשק הניהול -> שלוחה ריקה.
- הגדרות מתקדמות: הגדר
type=playfile. - קבצים: העלה את הקובץ
000.wavשיצרת בשלב הקודם.
שלב ד': ביצוע ההעברה למחשב המנותק
- פתח את Fldigi במחשב המנותק.
- הגדרות קליטה:
- וודא שהפרוטוקול הוא:
MT63-2000L. - ביטול סינון רעשים (SQL): בפינה הימנית התחתונה, וודא שכפתור SQL כבוי (לא ירוק) והמחוון שלידו למטה לגמרי. המחשב צריך "לשמוע הכל".
- ווליום: בהגדרות ווינדוס, וודא שהמיקרופון על 100%.
- וודא שהפרוטוקול הוא:
- לחץ קליק ימני על החלון הלבן (העליון) -> Clear.
- השידור:
- חייג בטלפון למערכת ימות המשיח.
- הצמד את הטלפון למיקרופון (או חבר כבל). שמור על שקט בחדר.
- בזמן השיחה:
- תראה פסים צהובים יורדים ב"מפל" השחור למטה.
- בחלון הלבן יופיע ג'יבריש, ואז הטקסט הנקי:
-----BEGIN CERTIFICATE-----.
שלב ה': שחזור הקובץ (במחשב המנותק)
- כשהשידור מסתיים, סמן ב-Fldigi את הטקסט רק מהשורה
-----BEGIN CERTIFICATE-----ועד-----END CERTIFICATE-----(כולל). - העתק את הטקסט (
Ctrl+C). - פתח "פנקס רשימות" (Notepad), הדבק ושמור בשם
received.txt. - פתח שורת פקודה (CMD) באותה תיקייה והרץ:
(שנה את הסיומתcertutil -decode received.txt final_file.pdfpdfלסיומת המקורית של הקובץ).
פתרון תקלות
- הטקסט יוצא "זבל" (ג'יבריש) ללא הפסקה: האות חלש מדי. הגבר את הווליום בטלפון לאזור 80%-90% וודא שמיקרופון המחשב על 100%.
-
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@חנוך-הכהן
כן, טכנית זה נכון, אבל האתגר הוא לא "לעשות ביפ", האתגר הוא לגרום לביפ הזה לשרוד.
זה כמו להגיד על Wi-Fi: "אז זה בסך הכל רדיו שעושה גלים באוויר במקום מוזיקה?
או על סיבים אופטיים: "אז זה בסך הכל פנס שמהבהב ממש מהר בקצה של צינור?תכלס התוצאה חמודה גם אם לא כל כך שימושית.
אבל אני תולה תקוות שאיך שהוא מישהו ימצא תדרך להוציא מזה משהו. -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@דוד-יצחק נכון!
כי לא נראה לי שיש סיכוי להעביר קבצים בזה כרגע.
זה גרסה רק כדי להראות את היכולות של זה. -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@מתכנת-חובב עכשיו שזה לטקסט זה המיר לי 2,697 תווים ל-7:10 דקות!
-
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@smct מוזר תנסה שוב
או שאולי המחשב שלך איטי מדאי -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@דוד-יצחק תפתח ותראה זה שונה לגמרי וכל הלוגיקה שונתה והיא תואמת בעיקר לטקסט.
-
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלאמי שרוצה דוגמה חייה לאחת הגרסאות המתקדמות שלי זה הקישור:
https://drive.google.com/file/d/1WtkPXOtK0Dm0_yI*****Csmf7FbsBG8NLrkAb/view?usp=sharingלהוריד כוכביות ולא לפרסם ללא הכוכביות.
יש הקלטה מוכנה להשמעה בקו שמספרו: 0794946346.
יש להיכנס לתוכנה ללחוץ על "התחל האזנה" ואז לחייג לקו ולהיכנס לשלוחה 1 לעשות על רמקול לסתום אוזנים ואז תתחילו לראות את הטקסט שג'ימני יצר שהוא מסביר על התוכנה.
שימו לב שבקוד הזה הטקסט חולק למקטעים ולכן גם אם יתפספס קטע אחד אתם תראו את הקטע הבא אחרי כמה שניות.הקוד בספוילר:
import sys import os import struct import threading import zlib import base64 import time import queue import datetime import numpy as np import sounddevice as sd import soundfile as sf from scipy.io import wavfile from scipy import signal as sig from reedsolo import RSCodec, ReedSolomonError import tkinter as tk from tkinter import filedialog, messagebox, ttk, scrolledtext # === הגדרות ליבה: STREAMER V3 === SAMPLE_RATE = 8000 BAUD_RATE = 50 RS_ECC_SYMBOLS = 20 INTERLEAVE_STEP = 10 FREQS = [1000, 1400, 1800, 2200] # 4-FSK # סנכרון SYNC_DURATION = 0.4 t_sync = np.arange(int(SAMPLE_RATE * SYNC_DURATION)) / SAMPLE_RATE SYNC_SIGNAL = sig.chirp(t_sync, f0=1000, f1=2200, t1=SYNC_DURATION, method='linear') # גודל מנה (תווים) CHUNK_SIZE = 120 TEXT_EXTENSIONS = ['.txt', '.csv', '.json', '.xml', '.html', '.php', '.py', '.js', '.ini', '.log'] # === לוגיקה מתמטית (Modem Engine) === def interleave(bits): n = len(bits) pad = (INTERLEAVE_STEP - (n % INTERLEAVE_STEP)) % INTERLEAVE_STEP src = bits + [0]*pad dst = [0]*len(src) rows = len(src)//INTERLEAVE_STEP for i in range(len(src)): dst[(i%INTERLEAVE_STEP)*rows + (i//INTERLEAVE_STEP)] = src[i] return dst, pad def deinterleave(bits, pad): n = len(bits) rows = n//INTERLEAVE_STEP dst = [0]*n for i in range(n): col = i // rows row = i % rows dst[row*INTERLEAVE_STEP + col] = bits[i] return dst[:-pad] if pad else dst def text2bits(b): res = [] for x in b: for i in range(7,-1,-1): res.append((x>>i)&1) return res def bits2bytes(b): res = bytearray() for i in range(0, len(b), 8): byte = b[i:i+8] if len(byte)<8: break v = 0 for bit in byte: v = (v<<1)|bit res.append(v) return bytes(res) # === Encoder === def encode_packet(data_bytes, packet_id, total_packets): try: compressed = zlib.compress(data_bytes, level=9) header = struct.pack('>HHH', packet_id, total_packets, len(compressed)) payload = header + compressed rsc = RSCodec(RS_ECC_SYMBOLS) encoded = rsc.encode(payload) bits = text2bits(encoded) shuffled, pad = interleave(bits) meta_header = struct.pack('>BH', pad, len(shuffled)) meta_bits = text2bits(meta_header) final_bits = meta_bits + shuffled if len(final_bits) % 2 != 0: final_bits.append(0) sps = int(SAMPLE_RATE / BAUD_RATE) t_sym = np.arange(sps) / SAMPLE_RATE phase = 0 waves = [] for i in range(0, len(final_bits), 2): val = (final_bits[i] << 1) | final_bits[i+1] freq = FREQS[val] w = np.sin(2 * np.pi * freq * t_sym + phase) waves.append(w) phase += 2 * np.pi * freq * (sps / SAMPLE_RATE) phase %= 2 * np.pi silence = np.zeros(int(SAMPLE_RATE * 0.25)) return np.concatenate([SYNC_SIGNAL, np.concatenate(waves), silence]) except: return None def generate_stream_file(filename, file_content, output_wav): try: ext = os.path.splitext(filename)[1].lower() is_text = ext in TEXT_EXTENSIONS chunks = [] if is_text: try: text_str = file_content.decode('utf-8', errors='ignore') curr = "" words = text_str.replace('\n', ' \n ').split(' ') for word in words: if len(word.encode('utf-8')) > CHUNK_SIZE: if curr: chunks.append(curr.encode('utf-8')); curr = "" chunks.append(word.encode('utf-8')); continue if len(curr.encode('utf-8')) + len(word.encode('utf-8')) < CHUNK_SIZE: curr += word + " " else: chunks.append(curr.encode('utf-8')); curr = word + " " if curr: chunks.append(curr.encode('utf-8')) except: chunks = [file_content[i:i+CHUNK_SIZE] for i in range(0, len(file_content), CHUNK_SIZE)] else: chunks = [file_content[i:i+CHUNK_SIZE] for i in range(0, len(file_content), CHUNK_SIZE)] total = len(chunks) audio_parts = [] t_wake = np.arange(int(SAMPLE_RATE * 2.0)) / SAMPLE_RATE wake = np.sin(2 * np.pi * 2200 * t_wake) audio_parts.append(wake) for i, chunk in enumerate(chunks): pkt = encode_packet(chunk, i+1, total) if pkt is not None: audio_parts.append(pkt) final_float = np.concatenate(audio_parts) mx = np.max(np.abs(final_float)) final_int16 = (final_float / mx * 32767).astype(np.int16) if mx > 0 else final_float.astype(np.int16) wavfile.write(output_wav, SAMPLE_RATE, final_int16) return True, f"{total}" except Exception as e: return False, str(e) # === Decoder === def decode_packet_from_stream(clean_audio): try: sps = int(SAMPLE_RATE / BAUD_RATE) num_syms = len(clean_audio) // sps if num_syms < 50: return None, 0 t = np.arange(sps) / SAMPLE_RATE refs = [np.exp(-2j * np.pi * f * t) for f in FREQS] bits_str = "" for i in range(num_syms): chunk = clean_audio[i*sps : (i+1)*sps] energies = [np.abs(np.dot(chunk, r))**2 for r in refs] bits_str += str((np.argmax(energies)>>1)&1) + str(np.argmax(energies)&1) if len(bits_str) < 24: return None, 0 meta_bits = [int(b) for b in bits_str[:24]] pad, bit_len = struct.unpack('>BH', bits2bytes(meta_bits)) if bit_len > 10000 or bit_len == 0: return None, 0 if len(bits_str) < 24 + bit_len: return None, 0 payload_bits = [int(b) for b in bits_str[24 : 24+bit_len]] raw_bits = deinterleave(payload_bits, pad) packet_bytes = bits2bytes(raw_bits) decoded = RSCodec(RS_ECC_SYMBOLS).decode(packet_bytes)[0] pkt_id, pkt_total, content_len = struct.unpack('>HHH', decoded[:6]) content = zlib.decompress(decoded[6 : 6+content_len]) samples_consumed = ((24 + bit_len) // 2) * sps return (pkt_id, pkt_total, content), samples_consumed except: return None, 0 # === GUI Professional === class AcousticReader: def __init__(self, root): self.root = root self.root.title("Acoustic Reader Pro") self.root.geometry("600x700") self.root.configure(bg="#2C3E50") self.audio_buffer = np.array([], dtype=float) self.is_rec = False self.q = queue.Queue() self.received_packets = {} # Styles style = ttk.Style() style.theme_use('clam') style.configure("TNotebook", background="#2C3E50", borderwidth=0) style.configure("TNotebook.Tab", background="#34495E", foreground="white", padding=[20, 10], font=("Segoe UI", 11)) style.map("TNotebook.Tab", background=[("selected", "#3498DB")]) style.configure("TFrame", background="#ECF0F1") tabs = ttk.Notebook(root) t_decode = ttk.Frame(tabs) # קבלה ראשון t_encode = ttk.Frame(tabs) # יצירה שני tabs.add(t_decode, text=" 📥 קליטת נתונים (חיבור AUX) ") tabs.add(t_encode, text=" 📤 יצירת קובץ (למנהל) ") tabs.pack(fill="both", expand=True, padx=10, pady=10) self.setup_decoder(t_decode) self.setup_encoder(t_encode) self.root.after(100, self.process_queue) def setup_decoder(self, parent): frame = tk.Frame(parent, bg="#ECF0F1") frame.pack(fill="both", expand=True, padx=20, pady=20) # Header tk.Label(frame, text="מערכת לקליטת עלונים וקבצים", font=("Segoe UI", 18, "bold"), bg="#ECF0F1", fg="#2C3E50").pack(pady=10) # Status & Vol status_frame = tk.Frame(frame, bg="#BDC3C7", bd=1, relief="sunken") status_frame.pack(fill="x", pady=10) self.canvas_vol = tk.Canvas(status_frame, width=300, height=15, bg="#95a5a6", highlightthickness=0) self.canvas_vol.pack(side="left", padx=10, pady=5) self.vol_bar = self.canvas_vol.create_rectangle(0,0,0,15, fill="#2ECC71") self.lbl_status = tk.Label(status_frame, text="ממתין להפעלה...", font=("Segoe UI", 10), bg="#BDC3C7") self.lbl_status.pack(side="right", padx=10) # Main Button self.btn_rec = tk.Button(frame, text="התחל האזנה", command=self.toggle_rec, font=("Segoe UI", 16, "bold"), bg="#27AE60", fg="white", activebackground="#2ECC71", activeforeground="white", bd=0, padx=20, pady=10) self.btn_rec.pack(pady=10) # Text Area tk.Label(frame, text="תוכן הקובץ המתקבל:", font=("Segoe UI", 11), bg="#ECF0F1", anchor="w").pack(fill="x") self.txt_display = scrolledtext.ScrolledText(frame, height=15, font=("Segoe UI", 12), bd=2, relief="flat") self.txt_display.pack(fill="both", expand=True, pady=5) self.txt_display.tag_config("info", foreground="#E67E22", font=("Segoe UI", 10, "bold")) self.txt_display.tag_config("content", foreground="#2C3E50") # Footer buttons btn_frame = tk.Frame(frame, bg="#ECF0F1") btn_frame.pack(pady=5) tk.Button(btn_frame, text="נקה מסך", command=self.clear_screen, bg="#95a5a6", fg="white", bd=0, padx=10).pack(side="left", padx=5) tk.Button(btn_frame, text="העתק טקסט", command=self.copy_text, bg="#3498DB", fg="white", bd=0, padx=10).pack(side="left", padx=5) def setup_encoder(self, parent): frame = tk.Frame(parent, bg="#ECF0F1") frame.pack(fill="both", expand=True, padx=20, pady=20) tk.Label(frame, text="יצירת קובץ שמע למערכת הטלפונית", font=("Segoe UI", 16, "bold"), bg="#ECF0F1", fg="#2C3E50").pack(pady=20) tk.Label(frame, text="בחר קובץ טקסט/מסמך להמרה.\nהמערכת תיצור קובץ WAV מותאם לשידור.", font=("Segoe UI", 11), bg="#ECF0F1", fg="#7F8C8D").pack(pady=10) tk.Button(frame, text="בחר קובץ והמר", command=self.do_enc, font=("Segoe UI", 14), bg="#2980B9", fg="white", activebackground="#3498DB", activeforeground="white", bd=0, padx=20, pady=15).pack(pady=40) self.lbl_enc = tk.Label(frame, text="", font=("Segoe UI", 11, "bold"), bg="#ECF0F1", fg="#27AE60") self.lbl_enc.pack() def clear_screen(self): self.txt_display.delete('1.0', tk.END) self.received_packets = {} def copy_text(self): self.root.clipboard_clear() self.root.clipboard_append(self.txt_display.get("1.0", tk.END)) messagebox.showinfo("הועתק", "התוכן הועתק ללוח") def do_enc(self): fn = filedialog.askopenfilename() if not fn: return sn = filedialog.asksaveasfilename(defaultextension=".wav", filetypes=[("WAV","*.wav")]) if not sn: return self.lbl_enc.config(text="מעבד... אנא המתן", fg="blue") self.root.update() try: with open(fn,'rb') as f: c=f.read() ok, msg = generate_stream_file(fn, c, sn) if ok: self.lbl_enc.config(text=f"הצלחה! נוצר קובץ עם {msg} מנות.", fg="#27AE60") else: self.lbl_enc.config(text=f"שגיאה: {msg}", fg="#C0392B") except Exception as e: self.lbl_enc.config(text=f"שגיאה: {e}", fg="#C0392B") def toggle_rec(self): if not self.is_rec: self.is_rec = True self.btn_rec.config(text="⏹️ עצור הקשבה", bg="#C0392B", activebackground="#E74C3C") self.audio_buffer = np.array([], dtype=float) self.lbl_status.config(text="מקשיב לקו... (נא להשמיע)", fg="#2980B9") self.clear_screen() threading.Thread(target=self.rec_thread).start() else: self.is_rec = False self.btn_rec.config(text="התחל האזנה", bg="#27AE60", activebackground="#2ECC71") self.lbl_status.config(text="מוכן") def update_vol(self, indata): peak = np.max(np.abs(indata)) / 32768.0 w = min(300, int(peak * 300)) c = "#2ECC71" if w < 200 else "#E74C3C" self.canvas_vol.coords(self.vol_bar, 0, 0, w, 15) self.canvas_vol.itemconfig(self.vol_bar, fill=c) def rec_thread(self): def cb(i, f, t, s): self.q.put(i.copy()) # שימוש בברירת מחדל של המערכת (ללא device index) try: with sd.InputStream(samplerate=SAMPLE_RATE, channels=1, callback=cb): while self.is_rec: sd.sleep(100) except Exception as e: self.is_rec = False messagebox.showerror("Error", f"שגיאת מיקרופון: {e}") def process_queue(self): try: while not self.q.empty(): chunk = self.q.get_nowait().flatten() self.update_vol(chunk * 32767) self.audio_buffer = np.concatenate((self.audio_buffer, chunk)) if len(self.audio_buffer) > SAMPLE_RATE * 15: self.audio_buffer = self.audio_buffer[-SAMPLE_RATE*15:] self.try_decode() except: pass self.root.after(50, self.process_queue) def try_decode(self): if len(self.audio_buffer) < 4000: return buff = self.audio_buffer.copy() sos = sig.butter(4, [800, 2400], btype='bandpass', fs=SAMPLE_RATE, output='sos') clean = sig.sosfilt(sos, buff) mx = np.max(np.abs(clean)) if mx > 0.01: clean /= mx corr = sig.correlate(clean, SYNC_SIGNAL, mode='valid') peaks, _ = sig.find_peaks(np.abs(corr), height=5, distance=SAMPLE_RATE) for peak_idx in peaks: start_data = peak_idx + len(SYNC_SIGNAL) if len(clean) > start_data + 500: audio_chunk = clean[start_data:] result, consumed = decode_packet_from_stream(audio_chunk) if result: pkt_id, total, content = result if pkt_id not in self.received_packets: self.received_packets[pkt_id] = True try: text = content.decode('utf-8') self.append_text(f"--- חלק {pkt_id} מתוך {total} ---\n", "info") self.append_text(text + "\n", "content") except: self.append_text(f"--- חלק {pkt_id}/{total} (קובץ בינארי) ---\n", "info") cut_pos = start_data + consumed + 100 if cut_pos < len(self.audio_buffer): self.audio_buffer = self.audio_buffer[cut_pos:] else: self.audio_buffer = np.array([], dtype=float) break def append_text(self, text, tag): self.txt_display.insert(tk.END, text, tag) self.txt_display.see(tk.END) if __name__ == "__main__": root = tk.Tk() app = AcousticReader(root) root.mainloop() -
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@דוד-יצחק אחד הדברים שאפשר לעשות כדי לדחוס מעבר לדחיסה רגילה זה להוריד את השימוש ב-UTF-8 כי זה מכפיל כל ביט.
השאלה היא אם אפשר לשלוח מהתוכנה DTMF לימות המשיח שימשיך להקלטה הבאה אם זה עבר טוב או שישמיע שוב אם זה לא עבר טוב.
את התפריט לאחר כל קובץ אפשר להגדיר עם ההקדרה הבאה במודול השמעת קבצים כמו שמופיע כאן:ניתן להגדיר תפריט לאחר כל השמעה
after_play_tfr=tfr_more_optionsברירת מחדל של התפריט M1459 לשמיעה חוזרת הקישו 0 למעבר להשמעה הבאה הקישו 1
ניתן להגדיר את התפריט מחדש ראה כאןי
-
המלצה | 🚀 [פרויקט מהפכני] העברת קבצים למחשב ללא אינטרנט דרך שיחה קולית (טלפון כשר!) - הקוד המלא@מתכנת-חובב אגב חשבתי על ראיון שיהיה שמיש לטקסט שאפשר לחתוך למקטעים וכל פעם שהוא שומע מקטע הוא מציג אותו למשתמש.
ניסיתי וזה עובד.
זה כבר אולי יותר הגיוני כך שאם לדוגמה אתה שולח לו טקסט ארוך אחרי דקה יש לו מה לקרא כבר.
אבל תכלס באמת זה לא נראה מדי מתקדם ובפרט שאין לנו אפשרות לשלוט על מה שימות המשיח מורידים מהאיכות ועל מה שהחברות תקשורת מורידים מהאיכות כך שלא נשאר הרבה אופציות איך לדחוס את זה הרבה יותר מזה ושזה יקלוט הכל
אבל האמת היא שאין לי כבל אוקס ואני מנסה את זה דרך הרמקול שזה מוריד את הרמה דרסטית אולי אני יקנה בהמשך ונראה מה הרמה ההכי דחוסה שאפשר לשלוח את זה.