diff --git a/src/routes/Player/ControlBar/ControlBar.js b/src/routes/Player/ControlBar/ControlBar.js
index e00f66d00..c9ba5cd7e 100644
--- a/src/routes/Player/ControlBar/ControlBar.js
+++ b/src/routes/Player/ControlBar/ControlBar.js
@@ -39,6 +39,9 @@ const ControlBar = React.forwardRef(({
onToggleSpeedMenu,
onToggleSideDrawer,
onToggleOptionsMenu,
+ videoScale,
+ videoScaleLabel,
+ onVideoScaleChanged,
onToggleStatisticsMenu,
onTouchEnd,
...props
@@ -176,6 +179,9 @@ const ControlBar = React.forwardRef(({
:
null
}
+
@@ -194,6 +200,9 @@ ControlBar.propTypes = {
volume: PropTypes.number,
muted: PropTypes.bool,
playbackSpeed: PropTypes.number,
+ videoScale: PropTypes.string,
+ videoScaleLabel: PropTypes.string,
+ onVideoScaleChanged: PropTypes.func,
subtitlesTracks: PropTypes.array,
audioTracks: PropTypes.array,
metaItem: PropTypes.object,
diff --git a/src/routes/Player/Indicator/Indicator.tsx b/src/routes/Player/Indicator/Indicator.tsx
index 7525fe1cd..b9290ad64 100644
--- a/src/routes/Player/Indicator/Indicator.tsx
+++ b/src/routes/Player/Indicator/Indicator.tsx
@@ -7,7 +7,13 @@ import styles from './Indicator.less';
type Property = {
label: string,
- format: (value: number) => string,
+ format: (value: number | string) => string,
+};
+
+const VIDEO_SCALE_LABELS: Record = {
+ 'contain': 'Fit',
+ 'cover': 'Crop',
+ 'fill': 'Stretch',
};
const PROPERTIES: Record = {
@@ -15,9 +21,13 @@ const PROPERTIES: Record = {
label: 'SUBTITLES_DELAY',
format: (value) => `${(value / 1000).toFixed(2)}s`,
},
+ 'videoScale': {
+ label: 'VIDEO_SCALE',
+ format: (value) => VIDEO_SCALE_LABELS[String(value)] || String(value),
+ },
};
-type VideoState = Record;
+type VideoState = Record;
type Props = {
className: string,
diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js
index 662717b70..add5c0c7c 100644
--- a/src/routes/Player/Player.js
+++ b/src/routes/Player/Player.js
@@ -97,6 +97,9 @@ const Player = ({ urlParams, queryParams }) => {
const isNavigating = React.useRef(false);
+ const VIDEO_SCALES = ['contain', 'cover', 'fill'];
+ const VIDEO_SCALE_LABELS = { contain: 'Fit', cover: 'Crop', fill: 'Stretch' };
+
const playbackSpeed = React.useRef(video.state.playbackSpeed || 1);
const pressTimer = React.useRef(null);
const longPress = React.useRef(false);
@@ -235,6 +238,13 @@ const Player = ({ urlParams, queryParams }) => {
}, []);
+ const onVideoScaleChanged = React.useCallback(() => {
+ const currentScale = video.state.videoScale || 'contain';
+ const currentIndex = VIDEO_SCALES.indexOf(currentScale);
+ const nextScale = VIDEO_SCALES[(currentIndex + 1) % VIDEO_SCALES.length];
+ video.setVideoScale(nextScale);
+ }, [video.state.videoScale]);
+
const onSubtitlesTrackSelected = React.useCallback((track) => {
video.setSubtitlesTrack(track?.id ?? null);
streamStateChanged({
@@ -999,6 +1009,9 @@ const Player = ({ urlParams, queryParams }) => {
onToggleSubtitlesMenu={toggleSubtitlesMenu}
onToggleAudioMenu={toggleAudioMenu}
onToggleSpeedMenu={toggleSpeedMenu}
+ videoScale={video.state.videoScale}
+ videoScaleLabel={VIDEO_SCALE_LABELS[video.state.videoScale || 'contain']}
+ onVideoScaleChanged={onVideoScaleChanged}
onToggleStatisticsMenu={toggleStatisticsMenu}
onToggleSideDrawer={toggleSideDrawer}
onMouseMove={onBarMouseMove}
diff --git a/src/routes/Player/useVideo.js b/src/routes/Player/useVideo.js
index b3a5d2e39..bfc0ec810 100644
--- a/src/routes/Player/useVideo.js
+++ b/src/routes/Player/useVideo.js
@@ -142,6 +142,10 @@ const useVideo = () => {
setProp('extraSubtitlesOffset', offset);
};
+ const setVideoScale = (scale) => {
+ setProp('videoScale', scale);
+ };
+
const setSubtitlesTextColor = (color) => {
setProp('subtitlesTextColor', color);
setProp('extraSubtitlesTextColor', color);
@@ -238,6 +242,7 @@ const useVideo = () => {
setSubtitlesBackgroundColor,
setSubtitlesOutlineColor,
setExtraSubtitlesTrack,
+ setVideoScale,
};
};