From b335d17d1f231b5921855f9a1190bcaa00cecec4 Mon Sep 17 00:00:00 2001 From: Giuseppe Falsone Date: Sun, 16 Mar 2025 18:28:31 +0100 Subject: [PATCH 1/4] feat(xtream): add option to select stream format (TS or M3U8) Add a new configuration option in the settings that allows choosing between TS and M3U8 stream formats. --- src/app/services/settings-store.service.ts | 3 +++ src/app/settings/settings.component.html | 27 ++++++++++++++++++- src/app/settings/settings.component.spec.ts | 2 ++ src/app/settings/settings.component.ts | 5 ++++ src/app/settings/settings.interface.ts | 2 ++ src/app/settings/stream-format.enum.ts | 7 +++++ .../live-stream-layout.component.ts | 3 ++- src/assets/i18n/en.json | 2 ++ 8 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/app/settings/stream-format.enum.ts diff --git a/src/app/services/settings-store.service.ts b/src/app/services/settings-store.service.ts index 4cd7dda5c..99a341f4c 100644 --- a/src/app/services/settings-store.service.ts +++ b/src/app/services/settings-store.service.ts @@ -8,6 +8,7 @@ import { } from '@ngrx/signals'; import { StorageMap } from '@ngx-pwa/local-storage'; import { firstValueFrom } from 'rxjs'; +import { StreamFormat } from '../settings/stream-format.enum'; import { Language } from '../settings/language.enum'; import { Settings, VideoPlayer } from '../settings/settings.interface'; import { Theme } from '../settings/theme.enum'; @@ -15,6 +16,7 @@ import { STORE_KEY } from '../shared/enums/store-keys.enum'; const DEFAULT_SETTINGS: Settings = { player: VideoPlayer.VideoJs, + streamFormat: StreamFormat.TsStreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, @@ -49,6 +51,7 @@ export const SettingsStore = signalStore( getSettings() { return { player: store.player(), + streamFormat: store.streamFormat(), language: store.language(), showCaptions: store.showCaptions(), theme: store.theme(), diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index 6fc0e8cbd..ce7d60d9b 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -70,7 +70,7 @@ - +
@@ -143,6 +143,31 @@
} +
+
+ {{ 'SETTINGS.STREAM_FORMAT' | translate }} +

{{ 'SETTINGS.STREAM_FORMAT_DESCRIPTION' | translate }}

+
+
+ + {{ + 'SETTINGS.VIDEO_PLAYER_PLACEHOLDER' | translate + }} + + {{ streamFormat.value }} + + + +
+
+
{{ 'SETTINGS.LANGUAGE' | translate }} diff --git a/src/app/settings/settings.component.spec.ts b/src/app/settings/settings.component.spec.ts index 18c09e8d0..4dc1aaf91 100644 --- a/src/app/settings/settings.component.spec.ts +++ b/src/app/settings/settings.component.spec.ts @@ -27,6 +27,7 @@ import { } from 'ng-mocks'; import { DataService } from '../services/data.service'; import { HeaderComponent } from '../shared/components'; +import { StreamFormat } from './stream-format.enum'; import { Language } from './language.enum'; import { SettingsComponent } from './settings.component'; import { VideoPlayer } from './settings.interface'; @@ -56,6 +57,7 @@ export class MockRouter { const DEFAULT_SETTINGS = { player: VideoPlayer.VideoJs, + streamFormat: StreamFormat.TsStreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 77f72150c..0a531d00d 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -49,6 +49,7 @@ import { HeaderComponent } from '../shared/components/header/header.component'; import * as PlaylistActions from '../state/actions'; import { selectIsEpgAvailable } from '../state/selectors'; import { SettingsService } from './../services/settings.service'; +import { StreamFormat } from './stream-format.enum'; import { Language } from './language.enum'; import { VideoPlayer } from './settings.interface'; import { Theme } from './theme.enum'; @@ -77,6 +78,9 @@ export class SettingsComponent implements OnInit { /** List with available languages as enum */ languageEnum = Language; + /** List with allowed formats as enum */ + streamFormatEnum = StreamFormat; + /** Flag that indicates whether the app runs in electron environment */ isTauri = this.dataService.getAppEnvironment() === 'tauri'; @@ -130,6 +134,7 @@ export class SettingsComponent implements OnInit { settingsForm = this.formBuilder.group({ player: [VideoPlayer.VideoJs], ...(this.isTauri ? { epgUrl: new FormArray([]) } : {}), + streamFormat: StreamFormat.TsStreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, diff --git a/src/app/settings/settings.interface.ts b/src/app/settings/settings.interface.ts index ddf8176d0..c18062c8e 100644 --- a/src/app/settings/settings.interface.ts +++ b/src/app/settings/settings.interface.ts @@ -1,3 +1,4 @@ +import { StreamFormat } from './stream-format.enum'; import { Language } from './language.enum'; import { Theme } from './theme.enum'; @@ -19,6 +20,7 @@ export enum VideoPlayer { export interface Settings { player: VideoPlayer; epgUrl: string[]; + streamFormat: StreamFormat; language: Language; showCaptions: boolean; theme: Theme; diff --git a/src/app/settings/stream-format.enum.ts b/src/app/settings/stream-format.enum.ts new file mode 100644 index 000000000..f85789b8a --- /dev/null +++ b/src/app/settings/stream-format.enum.ts @@ -0,0 +1,7 @@ +/** + * Enum with all the formats that are allowed in the application + */ +export enum StreamFormat { + TsStreamFormat = 'ts', + M3u8StreamFormat = 'm3u8', +} diff --git a/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts b/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts index b23a6fa6b..e4f6ebb3e 100644 --- a/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts +++ b/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts @@ -78,7 +78,8 @@ export class LiveStreamLayoutComponent implements OnInit { playLive(item: any) { const { serverUrl, username, password } = this.xtreamStore.currentPlaylist(); - const streamUrl = `${serverUrl}/live/${username}/${password}/${item.xtream_id}.m3u8`; + const streamFormat = this.settingsStore.streamFormat(); + const streamUrl = `${serverUrl}/live/${username}/${password}/${item.xtream_id}.${streamFormat}`; // TODO: offer option to select TS or m3u8 this.openPlayer(streamUrl, item.title, item.poster_url); this.xtreamStore.setSelectedItem(item); diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 6b40d5848..521c4df9d 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -119,6 +119,7 @@ "BACK_TO_HOME": "Back", "NEW_VERSION_AVAILABLE": "There is a new version available", "LATEST_VERSION": "You are using the latest version", + "STREAM_FORMAT": "Stream Format", "LANGUAGE": "Language", "SETTINGS_SAVED": "Success! Configuration was saved.", "THEME": "Visual theme", @@ -126,6 +127,7 @@ "ADD_EPG_SOURCE": "Add EPG source", "EPG_URL_ERROR": "The value is not a valid URL", "VIDEO_PLAYER_DESCRIPTION": "Select default video player", + "STREAM_FORMAT_DESCRIPTION": "Select default stream format", "LANGUAGE_DESCRIPTION": "Select language of the application", "THEME_DESCRIPTION": "Select visual theme of the application", "SHOW_CAPTIONS_DESCRIPTION": "Show or hide subtitles by default", From 0df7fae58c8c18512b86364b3e46b43bad9b9d85 Mon Sep 17 00:00:00 2001 From: Giuseppe Falsone Date: Sun, 16 Mar 2025 18:35:06 +0100 Subject: [PATCH 2/4] feat(i18n): add Italian translations for stream format options --- src/assets/i18n/it.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 7beaa812f..438754391 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -115,6 +115,7 @@ "BACK_TO_HOME": "Indietro", "NEW_VERSION_AVAILABLE": "È disponibile una nuova versione", "LATEST_VERSION": "Questa versione è aggiornata", + "STREAM_FORMAT": "Formato streaming", "LANGUAGE": "Lingua", "SETTINGS_SAVED": "La configurazione è stata salvata.", "THEME": "Tema visuale", @@ -122,6 +123,7 @@ "ADD_EPG_SOURCE": "Aggiungi sorgente EPG", "EPG_URL_ERROR": "Il valore non è una URL valida", "VIDEO_PLAYER_DESCRIPTION": "Seleziona lettore video predefinito", + "STREAM_FORMAT_DESCRIPTION": "Seleziona il formato di streaming predefinito", "LANGUAGE_DESCRIPTION": "Seleziona la lingua dell'applicazione", "THEME_DESCRIPTION": "Seleziona il tema visivo dell'applicazione", "SHOW_CAPTIONS_DESCRIPTION": "Visualizza/nascondi i sottotitoli per impostazione predefinita", From 9f40dea806019e932e20f27923af75b191921432 Mon Sep 17 00:00:00 2001 From: 4gray Date: Wed, 9 Apr 2025 20:35:36 +0200 Subject: [PATCH 3/4] refactor(settings): update default stream format to M3u8StreamFormat --- src/app/services/settings-store.service.ts | 2 +- src/app/settings/settings.component.spec.ts | 2 +- src/app/settings/settings.component.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/services/settings-store.service.ts b/src/app/services/settings-store.service.ts index 99a341f4c..9b6c6038a 100644 --- a/src/app/services/settings-store.service.ts +++ b/src/app/services/settings-store.service.ts @@ -16,7 +16,7 @@ import { STORE_KEY } from '../shared/enums/store-keys.enum'; const DEFAULT_SETTINGS: Settings = { player: VideoPlayer.VideoJs, - streamFormat: StreamFormat.TsStreamFormat, + streamFormat: StreamFormat.M3u8StreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, diff --git a/src/app/settings/settings.component.spec.ts b/src/app/settings/settings.component.spec.ts index 4dc1aaf91..af28ecac2 100644 --- a/src/app/settings/settings.component.spec.ts +++ b/src/app/settings/settings.component.spec.ts @@ -57,7 +57,7 @@ export class MockRouter { const DEFAULT_SETTINGS = { player: VideoPlayer.VideoJs, - streamFormat: StreamFormat.TsStreamFormat, + streamFormat: StreamFormat.M3u8StreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 0a531d00d..2adbdef8a 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -71,7 +71,7 @@ import { Theme } from './theme.enum'; ReactiveFormsModule, TranslateModule, MatDialogModule, - ] + ], }) export class SettingsComponent implements OnInit { @Input() isDialog = false; @@ -134,7 +134,7 @@ export class SettingsComponent implements OnInit { settingsForm = this.formBuilder.group({ player: [VideoPlayer.VideoJs], ...(this.isTauri ? { epgUrl: new FormArray([]) } : {}), - streamFormat: StreamFormat.TsStreamFormat, + streamFormat: StreamFormat.M3u8StreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, From c45bcb47cd942bd13766f39111678ae7a13cfd12 Mon Sep 17 00:00:00 2001 From: 4gray Date: Wed, 9 Apr 2025 20:35:57 +0200 Subject: [PATCH 4/4] refactor(i18n): update i18n --- src/assets/i18n/en.json | 2 +- src/assets/i18n/it.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index d008f82ed..dcb01a6f1 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -127,7 +127,7 @@ "ADD_EPG_SOURCE": "Add EPG source", "EPG_URL_ERROR": "The value is not a valid URL", "VIDEO_PLAYER_DESCRIPTION": "Select default video player", - "STREAM_FORMAT_DESCRIPTION": "Select default stream format", + "STREAM_FORMAT_DESCRIPTION": "Select default stream format (xtream)", "LANGUAGE_DESCRIPTION": "Select language of the application", "THEME_DESCRIPTION": "Select visual theme of the application", "SHOW_CAPTIONS_DESCRIPTION": "Show or hide subtitles by default", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 09b2b30de..d15f8aca8 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -123,7 +123,7 @@ "ADD_EPG_SOURCE": "Aggiungi sorgente EPG", "EPG_URL_ERROR": "Il valore non è una URL valida", "VIDEO_PLAYER_DESCRIPTION": "Seleziona lettore video predefinito", - "STREAM_FORMAT_DESCRIPTION": "Seleziona il formato di streaming predefinito", + "STREAM_FORMAT_DESCRIPTION": "Seleziona il formato di streaming predefinito (xtream)", "LANGUAGE_DESCRIPTION": "Seleziona la lingua dell'applicazione", "THEME_DESCRIPTION": "Seleziona il tema visivo dell'applicazione", "SHOW_CAPTIONS_DESCRIPTION": "Visualizza/nascondi i sottotitoli per impostazione predefinita",