@@ -869,3 +869,133 @@ describe("a copy sized to how large the video shows", () => {
869869 expect ( boxOf ( el ) ) . toBe ( "2436x4096" ) ;
870870 } ) ;
871871} ) ;
872+
873+ describe ( "preview quality: lighter copies of heavy files" , ( ) => {
874+ const HEAVY = { width : 3840 , height : 2160 , bitDepth : 8 , bitrate : 10_000_000 } ;
875+ const LIGHT = { width : 1280 , height : 720 , bitDepth : 8 , bitrate : 10_000_000 } ;
876+
877+ // A framed page showing a 1920x1080 stage at full size on a 1x screen: a 2048x1218 box.
878+ async function stage ( facts : Record < string , typeof HEAVY > , codecMap ?: Record < string , unknown > ) {
879+ vi . resetModules ( ) ;
880+ vi . spyOn ( window , "parent" , "get" ) . mockReturnValue ( { } as Window ) ;
881+ const mod = await import ( "./mediaProxy" ) ;
882+ window . __HF_MEDIA_SOURCE_FACTS__ = facts ;
883+ if ( codecMap ) window . __HF_MEDIA_CODEC_MAP__ = codecMap as never ;
884+ Object . defineProperty ( document . documentElement , "clientWidth" , {
885+ configurable : true ,
886+ value : 1920 ,
887+ } ) ;
888+ Object . defineProperty ( document . documentElement , "clientHeight" , {
889+ configurable : true ,
890+ value : 1080 ,
891+ } ) ;
892+ vi . spyOn ( window , "devicePixelRatio" , "get" ) . mockReturnValue ( 1 ) ;
893+ const video = ( src = "/video.mp4" ) => {
894+ const el = createVideo ( src ) ;
895+ stubCanPlayType ( el , "probably" ) ;
896+ el . getBoundingClientRect = ( ) => ( { width : 1920 , height : 1080 } ) as DOMRect ;
897+ return el ;
898+ } ;
899+ mod . setProxyDisplayScale ( 1 ) ;
900+ return { ...mod , video } ;
901+ }
902+
903+ const params = ( el : HTMLMediaElement ) => new URL ( el . src , document . baseURI ) . searchParams ;
904+
905+ afterEach ( ( ) => {
906+ delete ( window as { __HF_MEDIA_SOURCE_FACTS__ ?: unknown } ) . __HF_MEDIA_SOURCE_FACTS__ ;
907+ } ) ;
908+
909+ it ( "changes nothing at full quality" , async ( ) => {
910+ const { video, setPreviewQuality, maybeProxyProactively } = await stage ( {
911+ "/video.mp4" : HEAVY ,
912+ } ) ;
913+ const el = video ( ) ;
914+ maybeProxyProactively ( el ) ;
915+ setPreviewQuality ( 1 ) ;
916+ await settle ( ) ;
917+
918+ expect ( isProxied ( el ) ) . toBe ( false ) ;
919+ expect ( fetch ) . not . toHaveBeenCalled ( ) ;
920+ } ) ;
921+
922+ it ( "swaps a heavy file Chrome can play to a copy at the shown box times the level" , async ( ) => {
923+ const { video, setPreviewQuality } = await stage ( { "/video.mp4" : HEAVY } ) ;
924+ const el = video ( ) ;
925+
926+ setPreviewQuality ( 0.5 ) ;
927+ await settle ( ) ;
928+
929+ expect ( params ( el ) . get ( "hf-proxy" ) ) . toBe ( "auto" ) ;
930+ expect ( params ( el ) . get ( "hf-proxy-box" ) ) . toBe ( "1024x724" ) ;
931+ expect ( params ( el ) . get ( "hf-proxy-light" ) ) . toBe ( "1" ) ;
932+ } ) ;
933+
934+ it ( "leaves a file alone that is not heavy at that box" , async ( ) => {
935+ const { video, setPreviewQuality } = await stage ( { "/video.mp4" : LIGHT } ) ;
936+ const el = video ( ) ;
937+
938+ setPreviewQuality ( 0.5 ) ;
939+ await settle ( ) ;
940+
941+ expect ( isProxied ( el ) ) . toBe ( false ) ;
942+ } ) ;
943+
944+ it ( "puts the original back at full quality" , async ( ) => {
945+ const { video, setPreviewQuality } = await stage ( { "/video.mp4" : HEAVY } ) ;
946+ const el = video ( ) ;
947+ setPreviewQuality ( 0.5 ) ;
948+ await settle ( ) ;
949+ expect ( isProxied ( el ) ) . toBe ( true ) ;
950+
951+ setPreviewQuality ( 1 ) ;
952+
953+ expect ( el . getAttribute ( "src" ) ) . toBe ( "/video.mp4" ) ;
954+ expect ( el . load ) . toHaveBeenCalledTimes ( 2 ) ;
955+ } ) ;
956+
957+ it ( "lightens a video that appears after the level was lowered" , async ( ) => {
958+ const { video, setPreviewQuality, maybeProxyProactively } = await stage ( {
959+ "/video.mp4" : HEAVY ,
960+ } ) ;
961+ setPreviewQuality ( 0.25 ) ;
962+ const el = video ( ) ;
963+
964+ maybeProxyProactively ( el ) ;
965+ await settle ( ) ;
966+
967+ expect ( params ( el ) . get ( "hf-proxy-box" ) ) . toBe ( "512x362" ) ;
968+ } ) ;
969+
970+ it ( "sizes the copy a file cannot play without by the level too, and resizes it as the level moves" , async ( ) => {
971+ const { video, setPreviewQuality, maybeProxyProactively } = await stage (
972+ { "/video.mp4" : HEAVY } ,
973+ { "/video.mp4" : HEVC_ENTRY } ,
974+ ) ;
975+ const el = video ( ) ;
976+ stubCanPlayType ( el , "" ) ;
977+ maybeProxyProactively ( el ) ;
978+ await settle ( ) ;
979+ expect ( params ( el ) . get ( "hf-proxy-box" ) ) . toBe ( "2048x1218" ) ;
980+ expect ( params ( el ) . has ( "hf-proxy-light" ) ) . toBe ( false ) ;
981+
982+ setPreviewQuality ( 0.5 ) ;
983+ await settle ( ) ;
984+ expect ( params ( el ) . get ( "hf-proxy-box" ) ) . toBe ( "1024x724" ) ;
985+ expect ( params ( el ) . has ( "hf-proxy-light" ) ) . toBe ( false ) ;
986+
987+ setPreviewQuality ( 1 ) ;
988+ await settle ( ) ;
989+ expect ( params ( el ) . get ( "hf-proxy-box" ) ) . toBe ( "2048x1218" ) ;
990+ } ) ;
991+
992+ it ( "ignores a level that is not one of the four" , async ( ) => {
993+ const { video, setPreviewQuality } = await stage ( { "/video.mp4" : HEAVY } ) ;
994+ const el = video ( ) ;
995+
996+ setPreviewQuality ( 0.7 ) ;
997+ await settle ( ) ;
998+
999+ expect ( isProxied ( el ) ) . toBe ( false ) ;
1000+ } ) ;
1001+ } ) ;
0 commit comments