From 2a4ed686a81dc638124a1c1d40510d4b18112f86 Mon Sep 17 00:00:00 2001 From: Ben Hills Date: Wed, 14 Jun 2023 19:16:09 +0100 Subject: [PATCH] Improve speaker matching in SRT files; improve support for JSON single-word transcripts. --- lib/core/environment.dart | 2 +- .../audio/default_audio_player_service.dart | 17 ++-- .../podcast/mobile_podcast_service.dart | 79 +++++++++++++------ lib/ui/podcast/transcript_view.dart | 13 ++- pubspec.yaml | 2 +- 5 files changed, 79 insertions(+), 34 deletions(-) diff --git a/lib/core/environment.dart b/lib/core/environment.dart index 5dd39f4d..bd20df7d 100644 --- a/lib/core/environment.dart +++ b/lib/core/environment.dart @@ -17,7 +17,7 @@ class Environment { static const _applicationName = 'Anytime'; static const _applicationUrl = 'https://github.com/amugofjava/anytime_podcast_player'; static const _projectVersion = '1.3.0'; - static const _build = '90'; + static const _build = '91'; static var _agentString = userAgentAppString; diff --git a/lib/services/audio/default_audio_player_service.dart b/lib/services/audio/default_audio_player_service.dart index 98902d08..6fee9c54 100644 --- a/lib/services/audio/default_audio_player_service.dart +++ b/lib/services/audio/default_audio_player_service.dart @@ -733,15 +733,16 @@ class _DefaultAudioPlayerHandler extends BaseAudioHandler with SeekHandler { ); } else { _player = AudioPlayer( - /// Temporarily disable custom user agent to get over proxy issue in just_audio on iOS. - /// https://github.com/ryanheise/audio_service/issues/915 - // userAgent: Environment.userAgent(), + + /// Temporarily disable custom user agent to get over proxy issue in just_audio on iOS. + /// https://github.com/ryanheise/audio_service/issues/915 + // userAgent: Environment.userAgent(), audioLoadConfiguration: AudioLoadConfiguration( - androidLoadControl: AndroidLoadControl( - backBufferDuration: Duration(seconds: 45), - ), - darwinLoadControl: DarwinLoadControl(), - )); + androidLoadControl: AndroidLoadControl( + backBufferDuration: Duration(seconds: 45), + ), + darwinLoadControl: DarwinLoadControl(), + )); } /// List to events from the player itself, transform the player event to an audio service one diff --git a/lib/services/podcast/mobile_podcast_service.dart b/lib/services/podcast/mobile_podcast_service.dart index 08e8674c..89bb4f58 100644 --- a/lib/services/podcast/mobile_podcast_service.dart +++ b/lib/services/podcast/mobile_podcast_service.dart @@ -392,39 +392,74 @@ class MobilePodcastService extends PodcastService { return chapters; } + /// This method will load either of the supported transcript types. Currently, we do not support + /// word level highlighting of transcripts, therefore this routine will also group transcript + /// lines together by speaker and/or timeframe. @override Future loadTranscriptByUrl({@required TranscriptUrl transcriptUrl}) async { var subtitles = []; var result = await _loadTranscriptByUrl(transcriptUrl); - Subtitle subtitle; - Subtitle lastSubtitle; + var threshold = Duration(seconds: 5); + Subtitle groupSubtitle; if (result != null) { - for (var s in result.subtitles) { - var split = false; - var data = s.data; - - if (lastSubtitle != null) { - if (lastSubtitle.start == s.start) { - data = '${lastSubtitle.data} ${s.data}'; - lastSubtitle.data = data; - split = true; + for (var index = 0; index < result.subtitles.length; index++) { + var subtitle = result.subtitles[index]; + var completeGroup = true; + var data = subtitle.data; + + if (groupSubtitle != null) { + if (transcriptUrl.type == TranscriptFormat.json) { + if (groupSubtitle.speaker == subtitle.speaker && + subtitle.start.compareTo(groupSubtitle.start + threshold) < 0) { + /// We need to handle transcripts that have spaces between sentences, and those + /// which do not. + if (groupSubtitle.data.endsWith(' ') || subtitle.data.startsWith(' ') || subtitle.data.length == 1) { + data = '${groupSubtitle.data}${subtitle.data}'; + } else { + data = '${groupSubtitle.data} ${subtitle.data.trim()}'; + } + completeGroup = false; + } + } else { + if (groupSubtitle.start == subtitle.start) { + data = '${groupSubtitle.data} ${subtitle.data}'; + completeGroup = false; + } } + } else { + completeGroup = false; + groupSubtitle = Subtitle( + data: subtitle.data, + speaker: subtitle.speaker, + start: subtitle.start, + end: subtitle.end, + index: subtitle.index, + ); } - subtitle = Subtitle( - data: data, - speaker: s.speaker, - start: s.start, - end: s.end, - index: s.index, - ); + /// If we have a complete group, or we're the very last subtitle - add it. + if (completeGroup || index == result.subtitles.length - 1) { + groupSubtitle.data = groupSubtitle.data.trim(); - if (!split) { - subtitles.add(subtitle); - } + subtitles.add(groupSubtitle); - lastSubtitle = subtitle; + groupSubtitle = Subtitle( + data: subtitle.data, + speaker: subtitle.speaker, + start: subtitle.start, + end: subtitle.end, + index: subtitle.index, + ); + } else { + groupSubtitle = Subtitle( + data: data, + speaker: subtitle.speaker, + start: groupSubtitle.start, + end: subtitle.end, + index: groupSubtitle.index, + ); + } } } diff --git a/lib/ui/podcast/transcript_view.dart b/lib/ui/podcast/transcript_view.dart index a4ca1988..9e26230d 100644 --- a/lib/ui/podcast/transcript_view.dart +++ b/lib/ui/podcast/transcript_view.dart @@ -45,7 +45,7 @@ class _TranscriptViewState extends State { bool first = true; bool scrolling = false; String speaker = ''; - RegExp exp = RegExp(r'(^)(?[A-Za-z0-9\s]+)(:)'); + RegExp exp = RegExp(r'(^)(\[?)(?[A-Za-z0-9\s]+)(\]?)(\s?)(:)'); @override void initState() { @@ -68,10 +68,19 @@ class _TranscriptViewState extends State { _positionSubscription = audioBloc.playPosition.listen((event) { if (_itemScrollController.isAttached) { var transcript = event.episode?.transcript; - if (transcript != null && transcript.subtitles.isNotEmpty) { subtitle ??= transcript.subtitles[index]; + if (index == 0) { + var match = exp.firstMatch(subtitle.data); + + if (match != null) { + setState(() { + speaker = match.namedGroup('speaker'); + }); + } + } + // Our we outside the range of our current transcript. if (event.position.inMilliseconds < subtitle.start.inMilliseconds || event.position.inMilliseconds > subtitle.end.inMilliseconds) { diff --git a/pubspec.yaml b/pubspec.yaml index 69c934e4..64c196db 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: anytime description: Anytime Podcast Player -version: 1.3.0+90 +version: 1.3.0+91 environment: sdk: ">=2.10.0 <3.0.0"