Merge pull request #964 from Stremio/feat/player-download-subtitles

Player: Add option to download subtitles
This commit is contained in:
Tim 2025-07-07 14:27:32 +02:00 committed by GitHub
commit e98bdf2023
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 29 additions and 1 deletions

View file

@ -9,7 +9,7 @@ const { useServices } = require('stremio/services');
const Option = require('./Option'); const Option = require('./Option');
const styles = require('./styles'); const styles = require('./styles');
const OptionsMenu = ({ className, stream, playbackDevices }) => { const OptionsMenu = ({ className, stream, playbackDevices, extraSubtitlesTracks, selectedExtraSubtitlesTrackId }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { core } = useServices(); const { core } = useServices();
const platform = usePlatform(); const platform = usePlatform();
@ -25,6 +25,12 @@ const OptionsMenu = ({ className, stream, playbackDevices }) => {
const externalDevices = React.useMemo(() => { const externalDevices = React.useMemo(() => {
return playbackDevices.filter(({ type }) => type === 'external'); return playbackDevices.filter(({ type }) => type === 'external');
}, [playbackDevices]); }, [playbackDevices]);
const subtitlesTrackUrl = React.useMemo(() => {
const track = extraSubtitlesTracks?.find(({ id }) => id === selectedExtraSubtitlesTrackId);
return track?.fallbackUrl ?? track?.url ?? null;
}, [extraSubtitlesTracks, selectedExtraSubtitlesTrackId]);
const onCopyStreamButtonClick = React.useCallback(() => { const onCopyStreamButtonClick = React.useCallback(() => {
if (streamingUrl || downloadUrl) { if (streamingUrl || downloadUrl) {
navigator.clipboard.writeText(streamingUrl || downloadUrl) navigator.clipboard.writeText(streamingUrl || downloadUrl)
@ -52,6 +58,11 @@ const OptionsMenu = ({ className, stream, playbackDevices }) => {
platform.openExternal(streamingUrl || downloadUrl); platform.openExternal(streamingUrl || downloadUrl);
} }
}, [streamingUrl, downloadUrl]); }, [streamingUrl, downloadUrl]);
const onDownloadSubtitlesClick = React.useCallback(() => {
subtitlesTrackUrl && platform.openExternal(subtitlesTrackUrl);
}, [subtitlesTrackUrl]);
const onExternalDeviceRequested = React.useCallback((deviceId) => { const onExternalDeviceRequested = React.useCallback((deviceId) => {
if (streamingUrl) { if (streamingUrl) {
core.transport.dispatch({ core.transport.dispatch({
@ -94,6 +105,17 @@ const OptionsMenu = ({ className, stream, playbackDevices }) => {
: :
null null
} }
{
subtitlesTrackUrl ?
<Option
icon={'download'}
label={t('CTX_DOWNLOAD_SUBS')}
disabled={stream === null}
onClick={onDownloadSubtitlesClick}
/>
:
null
}
{ {
streamingUrl && externalDevices.map(({ id, name }) => ( streamingUrl && externalDevices.map(({ id, name }) => (
<Option <Option
@ -114,6 +136,8 @@ OptionsMenu.propTypes = {
className: PropTypes.string, className: PropTypes.string,
stream: PropTypes.object, stream: PropTypes.object,
playbackDevices: PropTypes.array, playbackDevices: PropTypes.array,
extraSubtitlesTracks: PropTypes.array,
selectedExtraSubtitlesTrackId: PropTypes.string,
}; };
module.exports = OptionsMenu; module.exports = OptionsMenu;

View file

@ -766,6 +766,8 @@ const Player = ({ urlParams, queryParams }) => {
className={classnames(styles['layer'], styles['menu-layer'])} className={classnames(styles['layer'], styles['menu-layer'])}
stream={player?.selected?.stream} stream={player?.selected?.stream}
playbackDevices={playbackDevices} playbackDevices={playbackDevices}
extraSubtitlesTracks={video.state.extraSubtitlesTracks}
selectedExtraSubtitlesTrackId={video.state.selectedExtraSubtitlesTrackId}
/> />
</ContextMenu> </ContextMenu>
<HorizontalNavBar <HorizontalNavBar
@ -903,6 +905,8 @@ const Player = ({ urlParams, queryParams }) => {
className={classnames(styles['layer'], styles['menu-layer'])} className={classnames(styles['layer'], styles['menu-layer'])}
stream={player.selected.stream} stream={player.selected.stream}
playbackDevices={playbackDevices} playbackDevices={playbackDevices}
extraSubtitlesTracks={video.state.extraSubtitlesTracks}
selectedExtraSubtitlesTrackId={video.state.selectedExtraSubtitlesTrackId}
/> />
: :
null null