diff options
Diffstat (limited to 'Biz')
| -rw-r--r-- | Biz/PodcastItLater/UI.py | 23 | ||||
| -rw-r--r-- | Biz/PodcastItLater/Worker.py | 28 |
2 files changed, 43 insertions, 8 deletions
diff --git a/Biz/PodcastItLater/UI.py b/Biz/PodcastItLater/UI.py index 00cf5e3..6825fd7 100644 --- a/Biz/PodcastItLater/UI.py +++ b/Biz/PodcastItLater/UI.py @@ -408,10 +408,27 @@ class AccountPage(Component[AnyChildren, AccountPageAttrs]): # User Info Section html.div( html.h5("Profile", classes=["mb-3"]), - html.p( + html.div( html.strong("Email: "), - user.get("email", ""), - classes=["mb-2"], + html.span(user.get("email", "")), + html.button( + "Change", + classes=[ + "btn", + "btn-sm", + "btn-outline-secondary", + "ms-2", + "py-0", + ], + hx_get="/settings/email/edit", + hx_target="closest div", + hx_swap="outerHTML", + ), + classes=[ + "mb-2", + "d-flex", + "align-items-center", + ], ), html.p( html.strong("Member since: "), diff --git a/Biz/PodcastItLater/Worker.py b/Biz/PodcastItLater/Worker.py index 3245fdd..251f614 100644 --- a/Biz/PodcastItLater/Worker.py +++ b/Biz/PodcastItLater/Worker.py @@ -60,6 +60,8 @@ MAX_RETRIES = 3 TTS_MODEL = "tts-1" TTS_VOICE = "alloy" MEMORY_THRESHOLD = 80 # Percentage threshold for memory usage +CROSSFADE_DURATION = 500 # ms for crossfading segments +PAUSE_DURATION = 1000 # ms for silence between segments class ShutdownHandler: @@ -358,7 +360,7 @@ class ArticleProcessor: content_audio: bytes, outro_audio: bytes, ) -> bytes: - """Combine intro, content, and outro with 1-second pauses. + """Combine intro, content, and outro with crossfades. Args: intro_audio: MP3 bytes for intro @@ -373,11 +375,27 @@ class ArticleProcessor: content = AudioSegment.from_mp3(io.BytesIO(content_audio)) outro = AudioSegment.from_mp3(io.BytesIO(outro_audio)) - # Create 1-second silence - pause = AudioSegment.silent(duration=1000) # milliseconds + # Create bridge silence (pause + 2 * crossfade to account for overlap) + bridge = AudioSegment.silent(duration=PAUSE_DURATION + 2 * CROSSFADE_DURATION) - # Combine segments with pauses - combined = intro + pause + content + pause + outro + def safe_append(seg1: AudioSegment, seg2: AudioSegment, crossfade: int) -> AudioSegment: + if len(seg1) < crossfade or len(seg2) < crossfade: + logger.warning( + "Segment too short for crossfade (%dms vs %dms/%dms), using concatenation", + crossfade, + len(seg1), + len(seg2), + ) + return seg1 + seg2 + return seg1.append(seg2, crossfade=crossfade) + + # Combine segments with crossfades + # Intro -> Bridge -> Content -> Bridge -> Outro + # This effectively fades out the previous segment and fades in the next one + combined = safe_append(intro, bridge, CROSSFADE_DURATION) + combined = safe_append(combined, content, CROSSFADE_DURATION) + combined = safe_append(combined, bridge, CROSSFADE_DURATION) + combined = safe_append(combined, outro, CROSSFADE_DURATION) # Export to bytes output = io.BytesIO() |
