mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-10-02 22:29:15 +00:00
Pre-generate support shorts, subtitle size, short like/dislike color
This commit is contained in:
parent
dc76934d0e
commit
3909343adc
8 changed files with 59 additions and 4 deletions
|
@ -603,6 +603,11 @@ class Settings : FragmentedStorageFileJson() {
|
||||||
else -> 2.0
|
else -> 2.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@AdvancedField
|
||||||
|
@FormField(R.string.shorts_pregenerate, FieldForm.TOGGLE, R.string.shorts_pregenerate_description, 28)
|
||||||
|
var shortsPregenerate: Boolean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@FormField(R.string.comments, "group", R.string.comments_description, 6)
|
@FormField(R.string.comments, "group", R.string.comments_description, 6)
|
||||||
|
|
|
@ -17,6 +17,7 @@ import com.futo.platformplayer.getOrNull
|
||||||
import com.futo.platformplayer.getOrThrow
|
import com.futo.platformplayer.getOrThrow
|
||||||
import com.futo.platformplayer.invokeV8
|
import com.futo.platformplayer.invokeV8
|
||||||
import com.futo.platformplayer.invokeV8Async
|
import com.futo.platformplayer.invokeV8Async
|
||||||
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.others.Language
|
import com.futo.platformplayer.others.Language
|
||||||
import com.futo.platformplayer.states.StateDeveloper
|
import com.futo.platformplayer.states.StateDeveloper
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
@ -57,12 +58,24 @@ class JSDashManifestRawAudioSource : JSSource, IAudioSource, IJSDashManifestRawS
|
||||||
hasGenerate = _obj.has("generate");
|
hasGenerate = _obj.has("generate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var _pregenerate: V8Deferred<String?>? = null;
|
||||||
|
fun pregenerateAsync(scope: CoroutineScope): V8Deferred<String?>? {
|
||||||
|
_pregenerate = generateAsync(scope);
|
||||||
|
return _pregenerate;
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateAsync(scope: CoroutineScope): V8Deferred<String?> {
|
override fun generateAsync(scope: CoroutineScope): V8Deferred<String?> {
|
||||||
if(!hasGenerate)
|
if(!hasGenerate)
|
||||||
return V8Deferred(CompletableDeferred(manifest));
|
return V8Deferred(CompletableDeferred(manifest));
|
||||||
if(_obj.isClosed)
|
if(_obj.isClosed)
|
||||||
throw IllegalStateException("Source object already closed");
|
throw IllegalStateException("Source object already closed");
|
||||||
|
|
||||||
|
val pregenerated = _pregenerate;
|
||||||
|
if(pregenerated != null) {
|
||||||
|
Logger.w("JSDashManifestRawAudioSource", "Returning pre-generated audio");
|
||||||
|
return pregenerated;
|
||||||
|
}
|
||||||
|
|
||||||
val plugin = _plugin.getUnderlyingPlugin();
|
val plugin = _plugin.getUnderlyingPlugin();
|
||||||
|
|
||||||
var result: V8Deferred<V8ValueString>? = null;
|
var result: V8Deferred<V8ValueString>? = null;
|
||||||
|
|
|
@ -18,6 +18,7 @@ import com.futo.platformplayer.getOrNull
|
||||||
import com.futo.platformplayer.getOrThrow
|
import com.futo.platformplayer.getOrThrow
|
||||||
import com.futo.platformplayer.invokeV8
|
import com.futo.platformplayer.invokeV8
|
||||||
import com.futo.platformplayer.invokeV8Async
|
import com.futo.platformplayer.invokeV8Async
|
||||||
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.states.StateDeveloper
|
import com.futo.platformplayer.states.StateDeveloper
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -65,11 +66,22 @@ open class JSDashManifestRawSource: JSSource, IVideoSource, IJSDashManifestRawSo
|
||||||
hasGenerate = _obj.has("generate");
|
hasGenerate = _obj.has("generate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var _pregenerate: V8Deferred<String?>? = null;
|
||||||
|
fun pregenerateAsync(scope: CoroutineScope): V8Deferred<String?>? {
|
||||||
|
_pregenerate = generateAsync(scope);
|
||||||
|
return _pregenerate;
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateAsync(scope: CoroutineScope): V8Deferred<String?> {
|
override fun generateAsync(scope: CoroutineScope): V8Deferred<String?> {
|
||||||
if(!hasGenerate)
|
if(!hasGenerate)
|
||||||
return V8Deferred(CompletableDeferred(manifest));
|
return V8Deferred(CompletableDeferred(manifest));
|
||||||
if(_obj.isClosed)
|
if(_obj.isClosed)
|
||||||
throw IllegalStateException("Source object already closed");
|
throw IllegalStateException("Source object already closed");
|
||||||
|
val pregenerated = _pregenerate;
|
||||||
|
if(pregenerated != null) {
|
||||||
|
Logger.w("JSDashManifestRawSource", "Returning pre-generated video");
|
||||||
|
return pregenerated;
|
||||||
|
}
|
||||||
|
|
||||||
val plugin = _plugin.getUnderlyingPlugin();
|
val plugin = _plugin.getUnderlyingPlugin();
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ import com.futo.platformplayer.api.media.models.subtitles.ISubtitleSource
|
||||||
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
|
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
|
||||||
import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
|
import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
|
||||||
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManifestRawAudioSource
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManifestRawSource
|
||||||
import com.futo.platformplayer.constructs.Event0
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
import com.futo.platformplayer.constructs.Event3
|
import com.futo.platformplayer.constructs.Event3
|
||||||
|
@ -66,6 +68,8 @@ import com.futo.platformplayer.views.pills.OnLikeDislikeUpdatedArgs
|
||||||
import com.futo.platformplayer.views.platform.PlatformIndicator
|
import com.futo.platformplayer.views.platform.PlatformIndicator
|
||||||
import com.futo.platformplayer.views.video.FutoShortPlayer
|
import com.futo.platformplayer.views.video.FutoShortPlayer
|
||||||
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
|
||||||
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase.Companion.PREFERED_AUDIO_CONTAINERS
|
||||||
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase.Companion.PREFERED_VIDEO_CONTAINERS
|
||||||
import com.futo.polycentric.core.ApiMethods
|
import com.futo.polycentric.core.ApiMethods
|
||||||
import com.futo.polycentric.core.ContentType
|
import com.futo.polycentric.core.ContentType
|
||||||
import com.futo.polycentric.core.Models
|
import com.futo.polycentric.core.Models
|
||||||
|
@ -742,6 +746,23 @@ class ShortView : FrameLayout {
|
||||||
videoDetails = result
|
videoDetails = result
|
||||||
video = result
|
video = result
|
||||||
|
|
||||||
|
if(Settings.instance.playback.shortsPregenerate)
|
||||||
|
fragment.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
if(result != null) {
|
||||||
|
val prefVid = VideoHelper.selectBestVideoSource(result.video, Settings.instance.playback.getCurrentPreferredQualityPixelCount(), PREFERED_VIDEO_CONTAINERS);
|
||||||
|
val prefAud = VideoHelper.selectBestAudioSource(result.video, PREFERED_AUDIO_CONTAINERS, Settings.instance.playback.getPrimaryLanguage(context));
|
||||||
|
|
||||||
|
if(prefVid != null && prefVid is JSDashManifestRawSource) {
|
||||||
|
Logger.i(TAG, "Shorts pregenerating video (${result.name})");
|
||||||
|
prefVid.pregenerateAsync(fragment.lifecycleScope);
|
||||||
|
}
|
||||||
|
if(prefAud != null && prefAud is JSDashManifestRawAudioSource) {
|
||||||
|
Logger.i(TAG, "Shorts pregenerating audio (${result.name})");
|
||||||
|
prefAud.pregenerateAsync(fragment.lifecycleScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bottomSheet.video = result
|
bottomSheet.video = result
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import androidx.annotation.Dimension
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.media3.common.PlaybackParameters
|
import androidx.media3.common.PlaybackParameters
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
|
@ -65,6 +66,8 @@ class FutoShortPlayer(context: Context, attrs: AttributeSet? = null) :
|
||||||
videoView = findViewById(R.id.short_player_view)
|
videoView = findViewById(R.id.short_player_view)
|
||||||
progressBar = findViewById(R.id.short_player_progress_bar)
|
progressBar = findViewById(R.id.short_player_progress_bar)
|
||||||
|
|
||||||
|
videoView.subtitleView?.setFixedTextSize(Dimension.SP, 18F);
|
||||||
|
|
||||||
if (!isInEditMode) {
|
if (!isInEditMode) {
|
||||||
player = StatePlayer.instance.getShortPlayerOrCreate(context)
|
player = StatePlayer.instance.getShortPlayerOrCreate(context)
|
||||||
player.player.repeatMode = Player.REPEAT_MODE_ONE
|
player.player.repeatMode = Player.REPEAT_MODE_ONE
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
android:viewportHeight="960"
|
android:viewportHeight="960"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@color/colorPrimary"
|
||||||
android:pathData="M240,120L640,120L640,640L360,920L310,870Q303,863 298.5,851Q294,839 294,828L294,814L338,640L120,640Q88,640 64,616Q40,592 40,560L40,480Q40,473 41.5,465Q43,457 46,450L166,168Q175,148 196,134Q217,120 240,120ZM720,640L720,120L880,120L880,640L720,640Z"/>
|
android:pathData="M240,120L640,120L640,640L360,920L310,870Q303,863 298.5,851Q294,839 294,828L294,814L338,640L120,640Q88,640 64,616Q40,592 40,560L40,480Q40,473 41.5,465Q43,457 46,450L166,168Q175,148 196,134Q217,120 240,120ZM720,640L720,120L880,120L880,640L720,640Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960"
|
android:viewportHeight="960">
|
||||||
android:tint="?attr/colorControlNormal">
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@color/colorPrimary"
|
||||||
android:pathData="M720,840L320,840L320,320L600,40L650,90Q657,97 661.5,109Q666,121 666,132L666,146L622,320L840,320Q872,320 896,344Q920,368 920,400L920,480Q920,487 918.5,495Q917,503 914,510L794,792Q785,812 764,826Q743,840 720,840ZM240,320L240,840L80,840L80,320L240,320Z"/>
|
android:pathData="M720,840L320,840L320,320L600,40L650,90Q657,97 661.5,109Q666,121 666,132L666,146L622,320L840,320Q872,320 896,344Q920,368 920,400L920,480Q920,487 918.5,495Q917,503 914,510L794,792Q785,812 764,826Q743,840 720,840ZM240,320L240,840L80,840L80,320L240,320Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -435,6 +435,8 @@
|
||||||
<string name="allow_full_screen_portrait">Allow full-screen portrait when watching horizontal videos</string>
|
<string name="allow_full_screen_portrait">Allow full-screen portrait when watching horizontal videos</string>
|
||||||
<string name="delete_watchlist_on_finish">Delete from WatchLater when watched</string>
|
<string name="delete_watchlist_on_finish">Delete from WatchLater when watched</string>
|
||||||
<string name="delete_watchlist_on_finish_description">After you leave a video that you mostly watched, it will be removed from watch later.</string>
|
<string name="delete_watchlist_on_finish_description">After you leave a video that you mostly watched, it will be removed from watch later.</string>
|
||||||
|
<string name="shorts_pregenerate">Pre-generate shorts sources</string>
|
||||||
|
<string name="shorts_pregenerate_description">Generates short sources (when applicable) one video ahead</string>
|
||||||
<string name="seek_offset">Seek duration</string>
|
<string name="seek_offset">Seek duration</string>
|
||||||
<string name="min_playback_speed">Minimum Playback Speed</string>
|
<string name="min_playback_speed">Minimum Playback Speed</string>
|
||||||
<string name="min_playback_speed_description">Minimum Available Speed</string>
|
<string name="min_playback_speed_description">Minimum Available Speed</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue