@vkontakte/videoplayer-statistics 1.0.34 → 1.0.35-dev.f578f79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es2015.cjs.js +4 -4
- package/es2015.esm.js +4 -4
- package/es2018.cjs.js +4 -4
- package/es2018.esm.js +4 -4
- package/esnext.cjs.js +4 -4
- package/esnext.esm.js +4 -4
- package/evergreen.esm.js +4 -4
- package/index.d.ts +151 -53
- package/package.json +3 -3
package/evergreen.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vkontakte/videoplayer-statistics v1.0.
|
|
3
|
-
*
|
|
4
|
-
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-
|
|
2
|
+
* @vkontakte/videoplayer-statistics v1.0.35-dev.f578f79.0
|
|
3
|
+
* Wed, 10 May 2023 11:40:54 GMT
|
|
4
|
+
* https://st.mycdn.me/static/vkontakte-videoplayer/1-0-35/doc/
|
|
5
5
|
*/
|
|
6
|
-
import{ValueSubject as $,getExponentialDelay as B,ErrorCategory as u,now as A,assertNever as U,Subscription as v,Subject as L,fromEvent as H,isNonNullable as k}from"@vkontakte/videoplayer-shared/esnext.esm.js";import{VideoQuality as c,HttpConnectionType as y,VideoFormat as n,ChromecastState as C}from"@vkontakte/videoplayer-core/esnext.esm.js";import D from"lodash/debounce.js";const w="_one-stat_",m=(()=>{try{const t=Date.now().toString(),e=window.localStorage;e.setItem(t,t);const i=e.getItem(t)===t;return e.removeItem(t),i?e:null}catch{return null}})();function M(t){const e=m?m.getItem(w+t):null;if(e===null)return null;try{return JSON.parse(e)}catch{return null}}function q(t,e){try{m&&m.setItem(w+t,JSON.stringify(e))}catch{}}function K(t){m&&m.removeItem(w+t)}var N={get(t){return M(t)||null},set(t,e){q(t,e)},remove(t){K(t)}};function z(){const t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36);let i=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?e[o]="-":o===14?e[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),s=i&15,i=i>>4,e[o]=t[o===19?s&3|8:s]);return e.join("")}var l;(function(t){t.PROD="prod",t.VK_ALIAS="vk_alias",t.VIDEOTEST="videotest",t.TEST="test",t.AUTO="auto"})(l||(l={}));var h;(function(t){t.Q144P="144",t.Q240P="240",t.Q360P="360",t.Q480P="480",t.Q720P="720",t.Q1080P="1080",t.Q1440P="1440",t.Q2160P="2160",t.Q4320P="4320",t.UNKNOWN="unknown"})(h||(h={}));var P;(function(t){t.CHROMECAST="chromecast",t.APPLE_TV="appletv",t.PIP="pip",t.HEADPHONES="externalHeadphones",t.SCREEN=""})(P||(P={}));var d;(function(t){t.MP4="mp4",t.DASH="dash",t.DASH_SEP="dash_sep",t.ONDEMAND_DASH="ondemand_dash",t.HLS="hls",t.ONDEMAND_HLS="ondemand_hls",t.WEBM="webm",t.RTMP="rtmp",t.UNKNOWN="unknown"})(d||(d={}));var T;(function(t){t.AUTO="auto",t.MANUAL=""})(T||(T={}));var _;(function(t){t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3"})(_||(_={}));var E;(function(t){t[t.YES=1]="YES",t[t.NO=0]="NO"})(E||(E={}));const I="1.0.34",Q="evergreen.esm.js",W="CIOPGQJGDIHBABABA",O={[l.PROD]:"https://api.ok.ru",[l.VK_ALIAS]:"https://api.mycdn.me",[l.VIDEOTEST]:"https://videotestapi.ok.ru/api",[l.TEST]:"https://apitest.ok.ru",[l.AUTO]:""},F={start:1e3,factor:1.5,max:5*60*1e3,random:.1};var p;(function(t){t[t.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",t[t.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",t[t.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",t[t.AUTH_LOGIN=401]="AUTH_LOGIN"})(p||(p={}));class V{params;uuid;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new $(!1);backoffTimeoutId;constructor(e){this.params=e;const i=N.get("uuid");i?this.uuid=String(i):(this.uuid=z(),N.set("uuid",this.uuid))}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const i="log.externalLog",s=this.createLogParams(e),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,s,o)||this.logRequest(e)}async logRequest(e){const i="log.externalLog",s=this.createLogParams(e),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const a=async(r,g=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,s,o)}catch(f){if(!f||!("error_code"in f)){this.params.error$.next({id:"logRequestUnknown",category:u.NETWORK,message:`Unknown ${i} error`,thrown:f});return}const S=f?.error_code;switch(S){case p.PARAM_SESSION_EXPIRED:case p.PARAM_SESSION_KEY:case p.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),g>0?a(r,g-1):void 0;case p.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),g>0?a(r,g-1):void 0;default:{this.params.error$.next({id:`LogRequest#${S}`,category:u.EXTERNAL_API,message:`${i} error`,data:f});return}}}};return a(e)}destroy(){window.clearTimeout(this.backoffTimeoutId),this.backoffTimeoutId=0}async refreshAuthToken(){if(this.params.refreshAuthToken)return this.refreshAuthTokenPromise||(this.refreshAuthTokenPromise=this.params.refreshAuthToken().finally(()=>{this.refreshAuthTokenPromise=void 0})),this.refreshAuthTokenPromise}createLogParams(e){return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`${Q}:${I}`,platform:"WEB",items:e.map(i=>({...i,time:0,type:1}))})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const e=B(this.consequentAuthErrors,F);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:u.NETWORK,message:"Otherwise unhandle errror in authrization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e="auth.anonymLogin",i={session_data:{version:2,device_id:this.uuid,client_version:I.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(i.session_data.auth_token=this.authToken,i.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(e,i).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:u.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=s?.session_key??void 0,this.sessionKey)).catch(async s=>{this.sessionKey=void 0;const o=s?.error_code;switch(o){case p.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:u.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:u.NETWORK,message:"authorize error",thrown:s})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}}class G{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==l.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await fetch(e,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(e){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:u.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),O[l.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,i,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:e,queryParams:i,sessionKey:s}),a=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,a)}catch(r){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:u.NETWORK,message:"Unhandled beacon error",thrown:r,data:{method:e,params:i}})}return!1}async sendRequest(e,i,s){const o=A(),a=r=>{if(r instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(r.message)){this.params.error$.next({id:"Network",category:u.NETWORK,message:"Request failed",thrown:r});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:u.NETWORK,message:"Unhandled request error",thrown:r,data:{method:e,params:i,sessionKey:s,time:A()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),fetch(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:e,queryParams:i,sessionKey:s})}).then(r=>{const g=Number(r.headers.get("content-length"))===0,f=new Date(r.headers.get("date")??"").getTime(),S=A()-o;if(isFinite(f)&&this.timeSynchronisation.addServerTime(f,S),!g)return r.json().then(b=>Object.prototype.hasOwnProperty.call(b,"error_msg")?Promise.reject(b):b,a)},a)}_prepareQueryParams(e){const i=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&i.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([s,o])=>i.append(s,typeof o=="string"?o:JSON.stringify(o))),i}}const x=3e3,j=x*5;class J{api;error$;requestQueue=[];subscription;isPaused=!1;debouncedFlush=D(()=>{try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:u.WTF,message:String(e)??"Unknown logger error",thrown:e})}},x,{maxWait:j});constructor(e){this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe(i=>{i&&this.debouncedFlush()})}log(e){this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){this.requestQueue.length!==0&&(this.api.authorized$.getValue()?(e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}class X{offset=void 0;constructor(e){this.offset=e}getOffset(){return this.offset??0}setOffset(e){this.offset=e}now(){return Date.now()+(this.offset??0)}date(e=new Date){return e.setTime(e.getTime()+(this.offset??0)),e}addServerTime(e,i){const s=Date.now(),o=e-s-i/2;if(Math.abs(o)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(o):this.offset=Math.round(.2*o+(1-.2)*this.offset)}}const R=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,"0"),Y=t=>t&&{[c.INVARIANT]:h.UNKNOWN,[c.Q_144P]:h.Q144P,[c.Q_240P]:h.Q240P,[c.Q_360P]:h.Q360P,[c.Q_480P]:h.Q480P,[c.Q_720P]:h.Q720P,[c.Q_1080P]:h.Q1080P,[c.Q_1440P]:h.Q1440P,[c.Q_2160P]:h.Q2160P,[c.Q_4320P]:h.Q4320P}[t],Z=t=>t&&{[y.HTTP1]:_.HTTP1,[y.HTTP2]:_.HTTP2,[y.QUIC]:_.HTTP3}[t],ee=t=>{if(t!==void 0)switch(t){case n.MPEG:return d.MP4;case n.DASH:case n.DASH_LIVE:case n.DASH_LIVE_CMAF:return d.DASH;case n.DASH_SEP:return d.DASH_SEP;case n.DASH_ONDEMAND:return d.ONDEMAND_DASH;case n.DASH_WEBM:case n.DASH_LIVE_WEBM:return d.WEBM;case n.HLS:case n.HLS_LIVE:case n.HLS_LIVE_CMAF:return d.HLS;case n.HLS_ONDEMAND:return d.ONDEMAND_HLS;case n.WEB_RTC_LIVE:return d.RTMP;default:return U(t)}};class oe{api;logger;config;subscription=new v;timeSynchronisation=new X;experimental;statContext;vsid=R();fieldBlacklist=[];constructor(e,i){this.statContext=e,this.config={...i.config??{},requestRetryCount:1};const s=new L;this.experimental={error$:s};const o=new G({apiKey:W,apiBaseUrl:O[i.apiEnv],apiEnv:i.apiEnv,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new V({apiTransport:o,refreshAuthToken:i.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,error$:s}),this.logger=new J({api:this.api,error$:s}),this.subscription.add(H(window,"beforeunload").subscribe(()=>this.logger.flush(!0)))}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){let i;return new v().add(e.events.started$.subscribe(()=>{this.logStarted({position:e.info.position$.getValue()})})).add(e.events.looped$.subscribe(()=>{this.resetViewSession(),this.logStarted({position:e.info.position$.getValue()})})).add(e.events.seeked$.subscribe(()=>{this.logSeek()})).add(e.events.willPause$.subscribe(()=>{this.logPause({position:e.info.position$.getValue()})})).add(e.events.willResume$.subscribe(()=>{this.logPlay()})).add(e.events.managedError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.fatalError$.subscribe(({id:s})=>{this.logError({errorType:s})})).add(e.events.inited$.subscribe(()=>{this.logInited()})).add(e.events.canplay$.subscribe(s=>{this.logReady({time:s})})).add(e.events.firstBytes$.subscribe(s=>{this.logFirstBytes({time:s})})).add(e.events.firstFrame$.subscribe(s=>{this.logFirstFrame({time:s})})).add(e.events.watchCoverageRecord$.subscribe(s=>{this.logWatchCoverageRecord(s)})).add(e.events.watchCoverageLive$.subscribe(s=>{this.logWatchCoverageLive(s)})).add(e.info.isStalled$.subscribe(s=>{s?i=A():(k(i)&&this.logEmptyBuffer({duration:A()-i}),i=void 0)})).add(e.events.ended$.subscribe(()=>{const s=e.info.throughputEstimation$.getValue();k(s)&&this.logDownloadSpeed({speed:s/8})})).add(e.info.hostname$.subscribe(s=>{this.updateContext({cdnHostname:s})})).add(e.info.httpConnectionType$.subscribe(s=>{this.updateContext({connectionType:Z(s)})})).add(e.info.httpConnectionReused$.subscribe(s=>{this.updateContext({connectionReused:s})})).add(e.info.currentQuality$.subscribe(s=>{this.updateContext({quality:Y(s)})})).add(e.info.currentFormat$.subscribe(s=>{this.updateContext({contentType:ee(s)})})).add(e.info.chromecastState$.subscribe(s=>{this.updateContext({destination:s===C.CONNECTED?P.CHROMECAST:P.SCREEN})}))}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=R()}setFieldBlacklist(e=[]){this.fieldBlacklist=e}logInited(){this.log({operation:"init"})}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(e){this.log({operation:"play",param:String(Math.round(e.position))})}logPlay(){this.log({operation:"play_toggle"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(){this.log({operation:"seek"})}logFirstBytes(e){this.log({operation:"first_bytes",param:String(e.time)})}logFirstFrame(e){this.log({operation:"first_frame",param:String(e.time)})}logError(e){this.log({operation:"error",param:e.errorType})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`}),this.logger.flush(!0)}logWatchCoverageLive(e){const i=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:"watch_coverage_live",param:`${i}-${s}`}),this.logger.flush(!0)}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(e){this.log({operation:"download_speed",param:String(e.speed)})}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(e){this.log({operation:"adv",param:e})}logAdPaused(){this.log({operation:"adv",param:"pause"})}logAdResumed(){this.log({operation:"adv",param:"resume"})}logAdEnded(){this.log({operation:"adv",param:"ended"})}logAdSkipped(){this.log({operation:"adv",param:"skip"})}logAdClicked(){this.log({operation:"adv",param:"click"})}log(e){const i=this.createLogItem(e);this.logger.log(i)}createLogItem({operation:e,param:i}){const s=this.timeSynchronisation.now(),o={vsid:this.vsid,vid:this.statContext.movieId,quality:this.statContext.quality,dst:this.statContext.destination,ct:this.statContext.contentType,aid:this.statContext.albumId,place:this.statContext.place,cdn_host:this.statContext.cdnHostname,connection_type:this.statContext.connectionType,connection_reused:this.statContext.connectionReused===!0?E.YES:this.statContext.connectionReused===!1?E.NO:void 0,stat_type:this.statContext.autoplay===!0?T.AUTO:this.statContext.autoplay===!1?T.MANUAL:void 0,vk_playlist_id:this.statContext.vkPlaylistId,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode};i!==void 0&&(o.param=i);for(const a of this.fieldBlacklist)delete o[a];return{operation:e,timestamp:s,custom:o}}}export{l as ApiEnv,_ as ConnectionType,d as ContentType,oe as OneStat,h as Quality,P as ScreenDestination};
|
|
6
|
+
import{ValueSubject as U,safeStorage as B,getExponentialDelay as Y,ErrorCategory as g,now as p,assertNever as Q,Observable as X,Subscription as N,merge as x,fromEvent as I,filterChanged as j,map as J,filter as H,isNullable as D,Subject as Z,once as ee,combine as M,observableFrom as te,isNonNullable as y}from"@vkontakte/videoplayer-shared/esnext.esm.js";import se from"lodash/debounce.js";import{Surface as $,VideoQuality as A,HttpConnectionType as C,VideoFormat as c,PlaybackState as W}from"@vkontakte/videoplayer-core/esnext.esm.js";function ie(){const t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),e=new Array(36);let i=0,s,o;for(o=0;o<36;o++)o===8||o===13||o===18||o===23?e[o]="-":o===14?e[o]="4":(i<=2&&(i=33554432+Math.random()*16777216|0),s=i&15,i=i>>4,e[o]=t[o===19?s&3|8:s]);return e.join("")}var b;(function(t){t.PROD="prod",t.VK_ALIAS="vk_alias",t.VIDEOTEST="videotest",t.TEST="test",t.AUTO="auto"})(b||(b={}));var d;(function(t){t.Q144P="mobile",t.Q240P="lowest",t.Q360P="low",t.Q480P="medium",t.Q720P="high",t.Q1080P="fullhd",t.Q1440P="quadhd",t.Q2160P="ultrahd",t.UNKNOWN="unknown"})(d||(d={}));var l;(function(t){t.MP4="mp4",t.DASH="dash",t.DASH_SEP="dash_sep",t.ONDEMAND_DASH="ondemand_dash",t.HLS="hls",t.ONDEMAND_HLS="ondemand_hls",t.WEBM="webm",t.ONDEMAND_DASH_LIVE="ondemand_dash_live",t.ONDEMAND_HLS_LIVE="ondemand_hls_live",t.WEBRTC="webrtc",t.UNKNOWN="unknown",t.RTMP="rtmp"})(l||(l={}));var k;(function(t){t.AUTO="auto",t.MANUAL=""})(k||(k={}));var v;(function(t){t.HTTP1="http1",t.HTTP2="http2",t.HTTP3="http3"})(v||(v={}));var _;(function(t){t[t.YES=1]="YES",t[t.NO=0]="NO"})(_||(_={}));var T;(function(t){t.EXCELLENT="excellent",t.GOOD="good",t.POOR="poor"})(T||(T={}));var w;(function(t){t.PIP="pip",t.FULLSCREEN="fullscreen",t.EXTERNAL="external",t.PREFETCH="prefetch"})(w||(w={}));var O;(function(t){t.SLIDER="slider",t.DOUBLE_TAP="double_tap",t.TIME_CODE="time_code",t.EPISODE="episode",t.REWIND="rewind",t.LIVE="live",t.UNKNOWN="unknown"})(O||(O={}));const q="1.0.35-dev.f578f79.0",oe="evergreen.esm.js",ne="CIOPGQJGDIHBABABA",z={[b.PROD]:"https://api.ok.ru",[b.VK_ALIAS]:"https://api.mycdn.me",[b.VIDEOTEST]:"https://videotestapi.ok.ru/api",[b.TEST]:"https://apitest.ok.ru",[b.AUTO]:""},re="_one-stat_",K=`${re}uuid`,ae={start:1e3,factor:1.5,max:5*60*1e3,random:.1};var P;(function(t){t[t.PARAM_SESSION_EXPIRED=102]="PARAM_SESSION_EXPIRED",t[t.PARAM_SESSION_KEY=103]="PARAM_SESSION_KEY",t[t.PARAM_SIGNATURE=104]="PARAM_SIGNATURE",t[t.AUTH_LOGIN=401]="AUTH_LOGIN"})(P||(P={}));class ue{params;uuid;authToken;sessionKey;authorizePromise;refreshAuthTokenPromise;consequentAuthErrors=0;authorized$=new U(!1);backoffTimeoutId;constructor(e){this.params=e;const i=B.get(K);i?this.uuid=String(i):(this.uuid=ie(),B.set(K,this.uuid))}async authorize(e){return this.authToken=e??await this.refreshAuthToken(),this._authorizeWithBackoff()}logBeacon(e){const i="log.externalLog",s=this.createLogParams(e),o=this.sessionKey;if(!o)return;this.params.apiTransport.sendBeacon(i,s,o)||this.logRequest(e)}async logRequest(e){const i="log.externalLog",s=this.createLogParams(e),o=this.sessionKey??await this._authorizeWithBackoff();if(!o)return;const a=async(r,h=this.params.requestRetryCount)=>{try{return await this.params.apiTransport.sendRequest(i,s,o)}catch(u){if(!u||!("error_code"in u)){this.params.error$.next({id:"logRequestUnknown",category:g.NETWORK,message:`Unknown ${i} error`,thrown:u});return}const m=u?.error_code;switch(m){case P.PARAM_SESSION_EXPIRED:case P.PARAM_SESSION_KEY:case P.PARAM_SIGNATURE:return this.authorized$.next(!1),this.sessionKey=await this._authorizeWithBackoff(),h>0?a(r,h-1):void 0;case P.AUTH_LOGIN:return this.authorized$.next(!1),this.authToken=await this.refreshAuthToken(),this.sessionKey=await this._authorizeWithBackoff(),h>0?a(r,h-1):void 0;default:{this.params.error$.next({id:`LogRequest#${m}`,category:g.EXTERNAL_API,message:`${i} error`,data:u});return}}}};return a(e)}destroy(){window.clearTimeout(this.backoffTimeoutId),this.backoffTimeoutId=0}async refreshAuthToken(){if(this.params.refreshAuthToken)return this.refreshAuthTokenPromise||(this.refreshAuthTokenPromise=this.params.refreshAuthToken().finally(()=>{this.refreshAuthTokenPromise=void 0})),this.refreshAuthTokenPromise}createLogParams(e){return{collector:"ok.mobile.apps.video",data:JSON.stringify({application:`${oe}:${q}`,platform:this.params.mobile?"M_WEB":"WEB",items:e})}}_authorizeWithBackoff(){if(!this.consequentAuthErrors)return this._authorize();const e=Y(this.consequentAuthErrors,ae);return new Promise(i=>{this.backoffTimeoutId||(this.backoffTimeoutId=window.setTimeout(()=>{this._authorize().then(i).catch(s=>this.params.error$.next({id:"AuthorizeBackoff",category:g.NETWORK,message:"Otherwise unhandled error in authorization",thrown:s})).finally(()=>this.backoffTimeoutId=0)},e))})}async _authorize(){if(this.authorizePromise)return this.authorizePromise;this.sessionKey=void 0,this.authorized$.next(!1);const e="auth.anonymLogin",i={session_data:{version:2,device_id:this.uuid,client_version:q.split("-")[0],client_type:"SDK_JS"}};return this.authToken!==void 0&&(i.session_data.auth_token=this.authToken,i.session_data.version=3),this.authorizePromise=this.params.apiTransport.sendRequest(e,i).then(s=>((!s||!s.session_key)&&this.params.error$.next({id:"AuthorizeFailed",category:g.EXTERNAL_API,message:"No session key",data:s}),this.sessionKey=s?.session_key??void 0,this.sessionKey)).catch(async s=>{this.sessionKey=void 0;const o=s?.error_code;switch(o){case P.AUTH_LOGIN:return this.authToken=await this.refreshAuthToken(),this._authorizeWithBackoff()}o?this.params.error$.next({id:`Authorize#${o}`,category:g.EXTERNAL_API,message:"authorize error",data:s}):this.params.error$.next({id:"AuthorizeUnknown",category:g.NETWORK,message:"authorize error",thrown:s})}).finally(()=>{this.authorizePromise=void 0,this.consequentAuthErrors=this.sessionKey?0:this.consequentAuthErrors+1,this.authorized$.next(this.sessionKey!==void 0)}),this.authorizePromise}}class he{apiKey;apiBaseUrl;apiEnv;timeSynchronisation;isApiBaseUrlFetched;params;constructor(e){this.params=e,this.apiKey=e.apiKey,this.apiEnv=e.apiEnv,this.apiBaseUrl=e.apiBaseUrl,this.timeSynchronisation=e.timeSynchronisation,this.isApiBaseUrlFetched=!1}async resolveApiBaseUrl(){if(this.apiEnv!==b.AUTO||this.isApiBaseUrlFetched)return this.apiBaseUrl;try{const e=atob("aHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT12aWRlby5fZW5kcG9pbnQub2sucnUmdHlwZT1UWFQ="),o=(await(await fetch(e,{method:"GET",mode:"cors",cache:"no-cache"})).json())?.Answer[0]?.data;if(!o)throw new Error("Wrong DNS response");return o}catch(e){return this.params.error$.next({id:"OneStat:ApiTransport:resolveApiBaseUrl",category:g.NETWORK,message:"Unhandled resolve api base url error",thrown:e}),z[b.VK_ALIAS]}finally{this.isApiBaseUrlFetched=!0}}sendBeacon(e,i,s){if(!window.Blob||!window.navigator.sendBeacon)return!1;const o=this._prepareQueryParams({method:e,queryParams:i,sessionKey:s}),a=new window.Blob([o.toString()],{type:"application/x-www-form-urlencoded"});try{return window.navigator.sendBeacon(`${this.apiBaseUrl}/fb.do`,a)}catch(r){this.params.error$.next({id:"OneStat:ApiTransport:sendBeacon",category:g.NETWORK,message:"Unhandled beacon error",thrown:r,data:{method:e,params:i}})}return!1}async sendRequest(e,i,s){const o=p(),a=r=>{if(r instanceof TypeError&&["Failed to fetch","NetworkError when attempting to fetch resource."].includes(r.message)){this.params.error$.next({id:"Network",category:g.NETWORK,message:"Request failed",thrown:r});return}this.params.error$.next({id:"OneStat:ApiTransport:sendRequest",category:g.NETWORK,message:"Unhandled request error",thrown:r,data:{method:e,params:i,sessionKey:s,time:p()-o}})};return this.apiBaseUrl=await this.resolveApiBaseUrl(),fetch(`${this.apiBaseUrl}/fb.do`,{method:"post",headers:{"Content-type":"application/x-www-form-urlencoded"},body:this._prepareQueryParams({method:e,queryParams:i,sessionKey:s})}).then(r=>{const h=Number(r.headers.get("content-length"))===0,u=new Date(r.headers.get("date")??"").getTime(),m=p()-o;if(isFinite(u)&&this.timeSynchronisation.addServerTime(u,m),!h)return r.json().then(n=>Object.prototype.hasOwnProperty.call(n,"error_msg")?Promise.reject(n):n,a)},a)}_prepareQueryParams(e){const i=new URLSearchParams({format:"JSON",method:e.method,application_key:this.apiKey});return e.sessionKey!==void 0&&i.append("session_key",e.sessionKey),Object.entries(e.queryParams).forEach(([s,o])=>i.append(s,typeof o=="string"?o:JSON.stringify(o))),i}}const G=3e3,ce=G*5;class de{api;error$;requestQueue=[];subscription;isPaused=!1;debouncedFlush=se(()=>{try{this.flush()}catch(e){this.error$.next({id:"LoggerError",category:g.WTF,message:String(e)??"Unknown logger error",thrown:e})}},G,{maxWait:ce});constructor(e){this.api=e.api,this.error$=e.error$,this.subscription=this.api.authorized$.subscribe(i=>{i&&this.debouncedFlush()})}log(e){console.log(e.operation,e.custom.param,e),this.requestQueue.push(e),this.isPaused||this.debouncedFlush()}flush(e=!1){this.requestQueue.length!==0&&(this.api.authorized$.getValue()?(console.log("Sending",this.requestQueue.length,"events",this.requestQueue),e?this.api.logBeacon(this.requestQueue):this.api.logRequest(this.requestQueue),this.requestQueue=[]):this.api.authorize(),this.debouncedFlush.cancel())}pause(){this.isPaused=!0,this.debouncedFlush.cancel()}resume(){this.isPaused=!1,this.debouncedFlush()}destroy(){this.subscription.unsubscribe()}}const le=()=>{let t,e;try{t=window.self!==window.top}catch(s){s instanceof DOMException&&s.name==="SecurityError"?t=!0:(t=!1,console.error(s))}try{window.location.ancestorOrigins&&(e=window.location.ancestorOrigins[window.location.ancestorOrigins.length-1])}catch(s){console.error(s)}try{!e&&document.referrer&&(e=document.referrer)}catch(s){console.error(s)}const i=e?new URL(e).hostname:void 0;return{isEmbed:t,host:i}},fe=t=>t&&{[A.INVARIANT]:d.UNKNOWN,[A.Q_144P]:d.Q144P,[A.Q_240P]:d.Q240P,[A.Q_360P]:d.Q360P,[A.Q_480P]:d.Q480P,[A.Q_720P]:d.Q720P,[A.Q_1080P]:d.Q1080P,[A.Q_1440P]:d.Q1440P,[A.Q_2160P]:d.Q2160P,[A.Q_4320P]:d.UNKNOWN}[t],V=t=>t&&{[C.HTTP1]:v.HTTP1,[C.HTTP2]:v.HTTP2,[C.QUIC]:v.HTTP3}[t],pe=t=>{if(t!==void 0)switch(t){case c.MPEG:return l.MP4;case c.DASH:case c.DASH_LIVE:return l.DASH;case c.DASH_SEP:return l.DASH_SEP;case c.DASH_ONDEMAND:return l.ONDEMAND_DASH;case c.DASH_WEBM:case c.DASH_LIVE_WEBM:return l.WEBM;case c.DASH_LIVE_CMAF:return l.ONDEMAND_DASH_LIVE;case c.HLS:case c.HLS_LIVE:return l.HLS;case c.HLS_ONDEMAND:return l.ONDEMAND_HLS;case c.HLS_LIVE_CMAF:return l.ONDEMAND_HLS_LIVE;case c.WEB_RTC_LIVE:return l.WEBRTC;default:return Q(t)}},L=t=>{if(t!==void 0)switch(t){case $.NONE:case $.INLINE:return;case $.FULLSCREEN:return w.FULLSCREEN;case $.SECOND_SCREEN:return w.EXTERNAL;case $.PIP:return w.PIP;default:return Q(t)}},ge=t=>{switch(t){case"slow-2g":return T.POOR;case"2g":return T.POOR;case"3g":return T.GOOD;case"4g":return T.EXCELLENT}};class me{offset=void 0;constructor(e){this.offset=e}getOffset(){return this.offset??0}setOffset(e){this.offset=e}now(){return Date.now()+(this.offset??0)}date(e=new Date){return e.setTime(e.getTime()+(this.offset??0)),e}addServerTime(e,i){const s=Date.now(),o=e-s-i/2;if(Math.abs(o)<1e3){this.offset=0;return}this.offset===void 0?this.offset=Math.round(o):this.offset=Math.round(.2*o+(1-.2)*this.offset)}}const F=()=>Math.floor(Math.random()*2**32).toString(36).padStart(8,"0"),Ee=t=>new X(e=>{const i=new N,s=x(I(window,"beforeunload"),t.events.willDestruct$),o=new U(void 0);let a;t.info.isLive$.pipe(j()).subscribe(S=>{a&&(a.unsubscribe(),o.next(void 0)),S?a=t.info.liveTime$.pipe(J(R=>R&&R/1e3)).subscribe(o):a=t.info.position$.subscribe(o),i.add(a)});const{playing$:r,paused$:h}=t.events,u=t.events.willSeek$.pipe(H(()=>t.info.playbackState$.getValue()===W.PLAYING)),m=t.events.seeked$.pipe(H(()=>t.info.playbackState$.getValue()===W.PLAYING)),n=x(r,m),f=x(h,u,s,t.events.looped$);let E;return i.add(n.subscribe(()=>E=o.getValue())),i.add(f.subscribe(()=>{const S=o.getValue();D(E)||E===S||D(S)||(e.next({from:E,to:S}),E=void 0)})),i});class Se{api;logger;config;subscription=new N;timeSynchronisation=new me;experimental;statContext;vsid=F();isEmbed;embedParent;uiEvents;player;seekAction$=new U(O.UNKNOWN);constructor(e,i){this.statContext=e,this.config={...i.config??{},requestRetryCount:1};const s=new Z;this.experimental={error$:s};const o=new he({apiKey:ne,apiBaseUrl:z[i.apiEnv],apiEnv:i.apiEnv,error$:s,timeSynchronisation:this.timeSynchronisation});this.api=new ue({apiTransport:o,refreshAuthToken:i.refreshAuthToken,requestRetryCount:this.config.requestRetryCount,mobile:this.statContext.mobile??!1,error$:s}),this.logger=new de({api:this.api,error$:s});const{isEmbed:a,host:r}=le();this.isEmbed=a,this.embedParent=r,this.subscribe()}updateContext(e){this.statContext={...this.statContext,...e}}attachTo(e){const i=new N,s=(n,f)=>i.add(n.subscribe(f));s(e.events.willStart$,()=>{this.logActionPlay({position:e.info.position$.getValue()})}),s(e.events.looped$,()=>{this.resetViewSession(),this.logActionPlay({position:e.info.position$.getValue()})}),s(e.events.seeked$,()=>{this.logSeek({action:this.seekAction$.getValue(),time:e.info.position$.getValue()}),this.seekAction$.next(O.UNKNOWN)}),s(e.events.paused$,()=>{this.logPause({position:e.info.position$.getValue()})}),s(e.events.willResume$,()=>{this.logPlay()}),s(e.events.started$,()=>{this.statContext.clip&&(this.logWatchCoverageRecord({start:0,end:0}),this.logger.flush())}),s(Ee(e),n=>{const f=e.info.isLive$.getValue(),E={start:n.from,end:n.to};f?this.logWatchCoverageLive(E):this.logWatchCoverageRecord(E)});let o;s(e.info.isStalled$,n=>{n?o=p():(y(o)&&this.logEmptyBuffer({duration:p()-o}),o=void 0)});let a=!1;i.add(e.events.fatalError$.pipe(ee()).subscribe(()=>a=!0)),s(e.events.willStop$,()=>{if(e.info.isStalled$.getValue()){const f=y(o)?p()-o:void 0;this.logCloseAtEmptyBuffer({duration:f??0}),o=void 0}else a||this.logActionStop();this.logger.flush()}),s(e.events.managedError$,({id:n})=>{this.logError({fatal:!1,errorType:n})}),s(e.events.fatalError$,({id:n})=>{this.logError({fatal:!0,errorType:n})});let r,h,u=!1;s(e.events.firstBytes$,n=>{r=p(),this.logFirstBytes({time:n})}),s(e.events.willStart$,()=>h=p()),s(e.info.currentBuffer$,n=>{!u&&n&&n.end-n.start>0&&y(r)&&(this.logPlayerReady({duration:p()-r}),u=!0)}),s(e.events.firstFrame$,()=>{y(r)&&!u&&(this.logPlayerReady({duration:p()-r}),u=!0),y(h)&&this.logFirstFrame({time:p()-h})}),s(e.info.atLiveEdge$,n=>this.updateContext({liveEdge:n})),s(M({muted:e.info.muted$,volume:e.info.volume$}),({muted:n,volume:f})=>this.updateContext({audible:!n&&f>0})),s(e.info.currentQuality$,n=>this.updateContext({quality:fe(n)})),s(e.info.isAutoQualityEnabled$,n=>this.updateContext({autoQuality:n})),s(e.info.currentFormat$,n=>this.updateContext({contentType:pe(n)}));let m;return s(e.info.hostname$,n=>{this.updateContext({cdnHostname:n,failover:m!==void 0&&m!==n}),m=n}),s(e.info.throughputEstimation$,n=>this.updateContext({downloadSpeed:n})),s(e.info.httpConnectionType$,n=>{this.statContext.firstConnectionType||this.updateContext({firstConnectionType:V(n)}),this.updateContext({connectionType:V(n)})}),s(e.info.httpConnectionReused$,n=>{D(this.statContext.firstConnectionReused)&&this.updateContext({firstConnectionReused:n}),this.updateContext({connectionReused:n})}),s(e.info.surface$,n=>this.updateContext({mode:L(n)})),s(M({current:e.info.currentTextTrack$,available:e.info.availableTextTracks$}),({current:n,available:f})=>{const E=f.find(({id:S})=>S===n);this.updateContext({subtitles:E?.language})}),this.player=e,this.uiEvents&&this.attachToUi(this.uiEvents),this.subscription.add(i),i}attachToUi(e){this.uiEvents=e;const i=new N;return this.player&&(i.add(e.actionRewind$.subscribe(()=>{this.player&&(this.resetViewSession(),this.logActionPlay({position:this.player.info.position$.getValue()}))})),i.add(e.actionSeek$.subscribe(this.seekAction$)),i.add(e.inPiP$.subscribe(s=>{const o=s?w.PIP:L(this.player?.info.surface$.getValue());this.updateContext({mode:o})})),i.add(e.inFullscreen$.subscribe(s=>{const o=s?w.FULLSCREEN:L(this.player?.info.surface$.getValue());this.updateContext({mode:o})})),this.subscription.add(i)),i}attachToAds(e){const i=new N;return i.add(e.slotRequested$.subscribe(()=>this.logAdSlotRequest())).add(e.started$.subscribe(s=>this.logAdStarted(s))).add(e.paused$.subscribe(()=>this.logAdPaused())).add(e.resumed$.subscribe(()=>this.logAdResumed())).add(e.ended$.subscribe(()=>this.logAdEnded())).add(e.skipped$.subscribe(()=>this.logAdSkipped())).add(e.clicked$.subscribe(()=>this.logAdClicked())),this.subscription.add(i),i}authorize(e){return this.api.authorize(e)}pause(){this.logger.pause()}resume(){this.logger.resume()}destroy(){this.logger.flush(),this.subscription.unsubscribe(),this.api.destroy(),this.logger.destroy()}resetViewSession(){this.vsid=F()}setFieldBlacklist(){}logInited(){}logReady(e){this.log({operation:"player_ready",param:String(e.time)})}logStarted(...e){this.logActionPlay(...e)}logPlay(){this.log({operation:"play_toggle"})}logPause(e){this.log({operation:"pause",param:String(Math.round(e.position))})}logSeek(e){this.log({operation:"seek",param:e.action,time:e.time})}logFirstBytes(e){this.log({operation:"first_bytes",param:String(e.time)})}logFirstFrame(e){this.log({operation:"first_frame",param:String(e.time)})}logError(e){this.log({operation:"content_error",param:`${e.fatal?"fatal":"recoverable"}_${e.errorType}`})}logWatchCoverageRecord(e){this.log({operation:"watch_coverage_record",param:`${e.start}-${e.end}`})}logWatchCoverageLive(e){const i=e.start+this.timeSynchronisation.getOffset(),s=e.end+this.timeSynchronisation.getOffset();this.log({operation:"watch_coverage_live",param:`${i}-${s}`})}logEmptyBuffer(e){this.log({operation:"empty_buffer",param:String(e.duration)})}logDownloadSpeed(){}logAdSlotRequest(){this.log({operation:"adv",param:"slot_request"})}logAdStarted(e){this.log({operation:"adv",param:e})}logAdPaused(){this.log({operation:"adv",param:"pause"})}logAdResumed(){this.log({operation:"adv",param:"resume"})}logAdEnded(){this.log({operation:"adv",param:"ended"})}logAdSkipped(){this.log({operation:"adv",param:"skip"})}logAdClicked(){this.log({operation:"adv",param:"click"})}subscribe(){this.subscription.add(I(window,"beforeunload").subscribe(()=>this.logger.flush(!0)));const e=window.navigator.connection;e&&"onchange"in e&&"effectiveType"in e&&this.subscription.add(x(I(e,"change"),te(["init"])).subscribe(()=>this.updateContext({network:ge(e.effectiveType)})))}logPlayerReady(e){this.log({operation:"player_ready",param:String(Math.round(e.duration))})}logActionPlay(e){this.log({operation:"action_play",param:String(Math.round(e.position))})}logCloseAtEmptyBuffer(e){this.log({operation:"close_at_empty_buffer",param:String(Math.round(e.duration))})}logActionStop(){this.log({operation:"action_stop"})}log(e){const i=this.createLogItem(e);this.logger.log(i)}createLogItem({operation:e,param:i,time:s}){const o=this.timeSynchronisation.now(),a=e==="empty_buffer"||e==="close_at_empty_buffer"?this.statContext.connectionType:this.statContext.firstConnectionType,r=this.statContext.firstConnectionReused,h={vsid:this.vsid,vid:this.statContext.movieId,ct:this.statContext.contentType,place:this.isEmbed?"embed":this.statContext.place,quality:this.statContext.quality,cdn_host:this.statContext.cdnHostname,stat_type:this.statContext.autoplay===!0?k.AUTO:this.statContext.autoplay===!1?k.MANUAL:void 0,param:i,vk_app_id:this.statContext.vkAppId,track_code:this.statContext.trackCode,connection_type:a,connection_reused:r===!0?_.YES:r===!1?_.NO:void 0,cached_data:this.statContext.cached===!0?_.YES:this.statContext.cached===!1?_.NO:void 0,live:this.statContext.liveEdge?_.YES:void 0,muted:this.statContext.audible===!1?_.YES:void 0,mode:this.statContext.mode,subtitles:this.statContext.subtitles,download_speed:this.statContext.downloadSpeed,manual_quality:this.statContext.autoQuality?void 0:_.YES,ref_domain:this.embedParent,aid:this.statContext.albumId,vk_playlist_id:this.statContext.vkPlaylistId};return{operation:e,type:1,time:s,network:this.statContext.network,timestamp:o,custom:h}}}export{b as ApiEnv,v as ConnectionType,l as ContentType,Se as OneStat,d as Quality,O as SeekAction};
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ISubscription, IObservable, IError, Seconds, Milliseconds } from '@vkontakte/videoplayer-shared';
|
|
2
1
|
import { IPlayer } from '@vkontakte/videoplayer-core';
|
|
2
|
+
import { Kbps, IObservable, ISubscription, IError, Seconds, Milliseconds, Subscription } from '@vkontakte/videoplayer-shared';
|
|
3
3
|
|
|
4
4
|
declare enum ApiEnv {
|
|
5
5
|
PROD = "prod",
|
|
@@ -9,24 +9,16 @@ declare enum ApiEnv {
|
|
|
9
9
|
AUTO = "auto"
|
|
10
10
|
}
|
|
11
11
|
declare enum Quality {
|
|
12
|
-
Q144P = "
|
|
13
|
-
Q240P = "
|
|
14
|
-
Q360P = "
|
|
15
|
-
Q480P = "
|
|
16
|
-
Q720P = "
|
|
17
|
-
Q1080P = "
|
|
18
|
-
Q1440P = "
|
|
19
|
-
Q2160P = "
|
|
20
|
-
Q4320P = "4320",
|
|
12
|
+
Q144P = "mobile",
|
|
13
|
+
Q240P = "lowest",
|
|
14
|
+
Q360P = "low",
|
|
15
|
+
Q480P = "medium",
|
|
16
|
+
Q720P = "high",
|
|
17
|
+
Q1080P = "fullhd",
|
|
18
|
+
Q1440P = "quadhd",
|
|
19
|
+
Q2160P = "ultrahd",
|
|
21
20
|
UNKNOWN = "unknown"
|
|
22
21
|
}
|
|
23
|
-
declare enum ScreenDestination {
|
|
24
|
-
CHROMECAST = "chromecast",
|
|
25
|
-
APPLE_TV = "appletv",
|
|
26
|
-
PIP = "pip",
|
|
27
|
-
HEADPHONES = "externalHeadphones",
|
|
28
|
-
SCREEN = ""
|
|
29
|
-
}
|
|
30
22
|
declare enum ContentType {
|
|
31
23
|
MP4 = "mp4",
|
|
32
24
|
DASH = "dash",
|
|
@@ -35,8 +27,12 @@ declare enum ContentType {
|
|
|
35
27
|
HLS = "hls",
|
|
36
28
|
ONDEMAND_HLS = "ondemand_hls",
|
|
37
29
|
WEBM = "webm",
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
ONDEMAND_DASH_LIVE = "ondemand_dash_live",
|
|
31
|
+
ONDEMAND_HLS_LIVE = "ondemand_hls_live",
|
|
32
|
+
WEBRTC = "webrtc",
|
|
33
|
+
UNKNOWN = "unknown",
|
|
34
|
+
/** @deprecated сдк не поддерживает RTMP, не нужно его использовать */
|
|
35
|
+
RTMP = "rtmp"
|
|
40
36
|
}
|
|
41
37
|
declare enum StatType {
|
|
42
38
|
AUTO = "auto",
|
|
@@ -47,37 +43,75 @@ declare enum ConnectionType {
|
|
|
47
43
|
HTTP2 = "http2",
|
|
48
44
|
HTTP3 = "http3"
|
|
49
45
|
}
|
|
50
|
-
declare enum
|
|
46
|
+
declare enum Flag {
|
|
51
47
|
YES = 1,
|
|
52
48
|
NO = 0
|
|
49
|
+
}
|
|
50
|
+
declare enum Network {
|
|
51
|
+
EXCELLENT = "excellent",
|
|
52
|
+
GOOD = "good",
|
|
53
|
+
POOR = "poor"
|
|
54
|
+
}
|
|
55
|
+
declare enum Mode {
|
|
56
|
+
PIP = "pip",
|
|
57
|
+
FULLSCREEN = "fullscreen",
|
|
58
|
+
EXTERNAL = "external",
|
|
59
|
+
PREFETCH = "prefetch"
|
|
60
|
+
}
|
|
61
|
+
declare enum SeekAction {
|
|
62
|
+
SLIDER = "slider",
|
|
63
|
+
DOUBLE_TAP = "double_tap",
|
|
64
|
+
TIME_CODE = "time_code",
|
|
65
|
+
EPISODE = "episode",
|
|
66
|
+
REWIND = "rewind",
|
|
67
|
+
LIVE = "live",
|
|
68
|
+
UNKNOWN = "unknown"
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
interface ILogCustomData {
|
|
56
|
-
/**
|
|
57
|
-
* Id видео
|
|
58
|
-
*/
|
|
59
|
-
vid: number;
|
|
60
72
|
/**
|
|
61
73
|
* Сессия смотрения, уникальна для пользователя, контента, экземпляра плеера и одного просмотра
|
|
62
74
|
* См https://confluence.vk.team/display/VID/Video%20Session%20ID
|
|
63
75
|
*/
|
|
64
|
-
vsid
|
|
65
|
-
|
|
66
|
-
dst?: ScreenDestination;
|
|
76
|
+
vsid: string;
|
|
77
|
+
vid: number;
|
|
67
78
|
ct?: ContentType;
|
|
68
|
-
aid?: string;
|
|
69
79
|
place?: string;
|
|
80
|
+
quality?: Quality;
|
|
70
81
|
cdn_host?: string;
|
|
71
|
-
connection_type?: ConnectionType;
|
|
72
|
-
connection_reused?: ConnectionReused;
|
|
73
82
|
stat_type?: StatType;
|
|
74
|
-
|
|
83
|
+
param?: any;
|
|
75
84
|
vk_app_id?: string;
|
|
76
85
|
track_code?: string;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
connection_type?: ConnectionType;
|
|
87
|
+
connection_reused?: Flag;
|
|
88
|
+
cached_data?: Flag;
|
|
89
|
+
live?: Flag;
|
|
90
|
+
muted?: Flag;
|
|
91
|
+
mode?: Mode;
|
|
92
|
+
subtitles?: string;
|
|
93
|
+
failover?: Flag;
|
|
94
|
+
download_speed?: Kbps;
|
|
95
|
+
manual_quality?: Flag;
|
|
96
|
+
ref_domain?: string;
|
|
97
|
+
vk_playlist_id?: string;
|
|
98
|
+
aid?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface IUIEvents {
|
|
102
|
+
actionRewind$: IObservable<void>;
|
|
103
|
+
actionSeek$: IObservable<SeekAction>;
|
|
104
|
+
inPiP$: IObservable<boolean>;
|
|
105
|
+
inFullscreen$: IObservable<boolean>;
|
|
106
|
+
}
|
|
107
|
+
interface IAdsEvents {
|
|
108
|
+
slotRequested$: IObservable<void>;
|
|
109
|
+
started$: IObservable<string>;
|
|
110
|
+
paused$: IObservable<void>;
|
|
111
|
+
resumed$: IObservable<void>;
|
|
112
|
+
ended$: IObservable<void>;
|
|
113
|
+
skipped$: IObservable<void>;
|
|
114
|
+
clicked$: IObservable<void>;
|
|
81
115
|
}
|
|
82
116
|
|
|
83
117
|
interface IOneStat {
|
|
@@ -93,6 +127,8 @@ interface IOneStat {
|
|
|
93
127
|
*/
|
|
94
128
|
updateContext(context: Partial<IStatContext>): void;
|
|
95
129
|
attachTo(player: IPlayer): ISubscription;
|
|
130
|
+
attachToUi(uiEvents: IUIEvents): ISubscription;
|
|
131
|
+
attachToAds(adsEvents: IAdsEvents): ISubscription;
|
|
96
132
|
/**
|
|
97
133
|
* Ставит отправку событий на паузу. Они будут накапливаться до вызова `resume()`
|
|
98
134
|
*/
|
|
@@ -110,70 +146,107 @@ interface IOneStat {
|
|
|
110
146
|
*/
|
|
111
147
|
resetViewSession(): void;
|
|
112
148
|
/**
|
|
149
|
+
* @deprecated
|
|
113
150
|
* Отключает отправку полей событий
|
|
114
151
|
*/
|
|
115
152
|
setFieldBlacklist(fields: (keyof ILogCustomData)[]): void;
|
|
116
153
|
/**
|
|
117
|
-
*
|
|
154
|
+
* @deprecated
|
|
118
155
|
*/
|
|
119
156
|
logInited(): void;
|
|
120
157
|
/**
|
|
158
|
+
* @deprecated публично нужно использовать attachTo
|
|
121
159
|
* Плеер готов начать воспроизведение
|
|
122
160
|
*/
|
|
123
161
|
logReady(payload: IReadyPayload): void;
|
|
124
162
|
/**
|
|
163
|
+
* @deprecated публично нужно использовать attachTo
|
|
125
164
|
* Первый старт видео. Отправляется 1 раз, когда фактически началось воспроизведение ролика, а также после зацикливания, но не после паузы.
|
|
126
165
|
*
|
|
127
166
|
* В документации API может называться `play`
|
|
128
167
|
*/
|
|
129
168
|
logStarted(payload: IActionPlayPayload): void;
|
|
130
169
|
/**
|
|
170
|
+
* @deprecated публично нужно использовать attachTo
|
|
131
171
|
* Возобновление после паузы
|
|
132
172
|
*
|
|
133
173
|
* В документации API может называться `play_toggle`
|
|
134
174
|
*/
|
|
135
175
|
logPlay(): void;
|
|
136
176
|
/**
|
|
177
|
+
* @deprecated публично нужно использовать attachTo
|
|
137
178
|
* Постановка видео на паузу
|
|
138
179
|
*/
|
|
139
180
|
logPause(payload: IPausePayload): void;
|
|
140
181
|
/**
|
|
182
|
+
* @deprecated публично нужно использовать attachTo
|
|
141
183
|
* перемотка видео
|
|
142
184
|
*/
|
|
143
|
-
logSeek(): void;
|
|
185
|
+
logSeek(payload: ISeekPayload): void;
|
|
144
186
|
/**
|
|
187
|
+
* @deprecated публично нужно использовать attachTo
|
|
145
188
|
* Промежутки видео, которые были просмотрены пользователем.
|
|
146
189
|
* Время указывается в секундах от начала ролика (т.е. является позицией).
|
|
147
190
|
*/
|
|
148
191
|
logWatchCoverageRecord(payload: IWatchCoveragePayload): void;
|
|
149
192
|
/**
|
|
193
|
+
* @deprecated публично нужно использовать attachTo
|
|
150
194
|
* Промежутки видео, которые были просмотрены пользователем.
|
|
151
195
|
* Время указывается в виде UTC timestamp'ов.
|
|
152
196
|
*/
|
|
153
197
|
logWatchCoverageLive(payload: IWatchCoveragePayload): void;
|
|
154
198
|
/**
|
|
199
|
+
* @deprecated публично нужно использовать attachTo
|
|
155
200
|
* Буфер пуст и пользователь видит залипший кадр.
|
|
156
201
|
*/
|
|
157
202
|
logEmptyBuffer(payload: IEmptyBufferPayload): void;
|
|
158
203
|
/**
|
|
204
|
+
* @deprecated публично нужно использовать attachTo
|
|
159
205
|
* Получен первый кусок данных контента от сервера раздачи видео
|
|
160
206
|
*/
|
|
161
207
|
logFirstBytes(payload: IFirstBytesPayload): void;
|
|
162
208
|
/**
|
|
209
|
+
* @deprecated публично нужно использовать attachTo
|
|
163
210
|
* Пользователь увидел первый кадр
|
|
164
211
|
*/
|
|
165
212
|
logFirstFrame(payload: IFirstFramePayload): void;
|
|
213
|
+
/**
|
|
214
|
+
* @deprecated публично нужно использовать attachTo
|
|
215
|
+
* @param payload
|
|
216
|
+
*/
|
|
166
217
|
logDownloadSpeed(payload: IDownloadSpeedPayload): void;
|
|
167
218
|
/**
|
|
168
219
|
* произошла ошибка
|
|
169
220
|
*/
|
|
170
221
|
logError(payload: IErrorPayload): void;
|
|
222
|
+
/**
|
|
223
|
+
* @deprecated публично нужно использовать attachToAds
|
|
224
|
+
*/
|
|
171
225
|
logAdSlotRequest(): void;
|
|
226
|
+
/**
|
|
227
|
+
* @deprecated публично нужно использовать attachToAds
|
|
228
|
+
* @param sectionType
|
|
229
|
+
*/
|
|
172
230
|
logAdStarted(sectionType: string): void;
|
|
231
|
+
/**
|
|
232
|
+
* @deprecated публично нужно использовать attachToAds
|
|
233
|
+
*/
|
|
173
234
|
logAdPaused(): void;
|
|
235
|
+
/**
|
|
236
|
+
* @deprecated публично нужно использовать attachToAds
|
|
237
|
+
*/
|
|
174
238
|
logAdResumed(): void;
|
|
239
|
+
/**
|
|
240
|
+
* @deprecated публично нужно использовать attachToAds
|
|
241
|
+
*/
|
|
175
242
|
logAdEnded(): void;
|
|
243
|
+
/**
|
|
244
|
+
* @deprecated публично нужно использовать attachToAds
|
|
245
|
+
*/
|
|
176
246
|
logAdSkipped(): void;
|
|
247
|
+
/**
|
|
248
|
+
* @deprecated публично нужно использовать attachToAds
|
|
249
|
+
*/
|
|
177
250
|
logAdClicked(): void;
|
|
178
251
|
experimental: {
|
|
179
252
|
error$: IObservable<IError>;
|
|
@@ -191,6 +264,13 @@ interface IPausePayload {
|
|
|
191
264
|
*/
|
|
192
265
|
position: Seconds;
|
|
193
266
|
}
|
|
267
|
+
interface ISeekPayload {
|
|
268
|
+
/**
|
|
269
|
+
* Действие пользователя приведшее к перемотке
|
|
270
|
+
*/
|
|
271
|
+
action: SeekAction;
|
|
272
|
+
time: Seconds;
|
|
273
|
+
}
|
|
194
274
|
interface IReadyPayload {
|
|
195
275
|
/**
|
|
196
276
|
* время в миллисекундах с события inited
|
|
@@ -226,27 +306,34 @@ interface IErrorPayload {
|
|
|
226
306
|
* строка из символов(без пробелов): тип ошибки
|
|
227
307
|
*/
|
|
228
308
|
errorType: string;
|
|
309
|
+
fatal: boolean;
|
|
229
310
|
}
|
|
230
311
|
interface IStatContext {
|
|
231
|
-
|
|
232
|
-
* Ид видео
|
|
233
|
-
*/
|
|
312
|
+
mobile: boolean;
|
|
234
313
|
movieId: number;
|
|
314
|
+
vkAppId?: string;
|
|
315
|
+
clip?: boolean;
|
|
316
|
+
liveEdge?: boolean;
|
|
317
|
+
autoplay: boolean;
|
|
318
|
+
audible?: boolean;
|
|
235
319
|
quality?: Quality;
|
|
236
|
-
|
|
320
|
+
autoQuality?: boolean;
|
|
237
321
|
contentType?: ContentType;
|
|
238
322
|
albumId?: string;
|
|
239
323
|
vkPlaylistId?: string;
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Раздел сайта на котором играет видео: Лента, плеер, личные сообщения, ...
|
|
243
|
-
*/
|
|
324
|
+
trackCode?: string;
|
|
244
325
|
place?: string;
|
|
245
326
|
cdnHostname?: string;
|
|
327
|
+
downloadSpeed?: Kbps;
|
|
246
328
|
connectionType?: ConnectionType;
|
|
247
329
|
connectionReused?: boolean;
|
|
248
|
-
|
|
249
|
-
|
|
330
|
+
firstConnectionType?: ConnectionType;
|
|
331
|
+
firstConnectionReused?: boolean;
|
|
332
|
+
network?: Network;
|
|
333
|
+
cached?: boolean;
|
|
334
|
+
mode?: Mode;
|
|
335
|
+
subtitles?: string;
|
|
336
|
+
failover?: boolean;
|
|
250
337
|
}
|
|
251
338
|
interface IConfig {
|
|
252
339
|
requestRetryCount: number;
|
|
@@ -271,29 +358,35 @@ declare class OneStat implements IOneStat {
|
|
|
271
358
|
};
|
|
272
359
|
private statContext;
|
|
273
360
|
private vsid;
|
|
274
|
-
private
|
|
361
|
+
private isEmbed;
|
|
362
|
+
private embedParent;
|
|
363
|
+
private uiEvents;
|
|
364
|
+
private player;
|
|
365
|
+
private seekAction$;
|
|
275
366
|
constructor(statContext: IStatContext, params: IConstructorParams);
|
|
276
367
|
updateContext(newContext: Partial<IStatContext>): void;
|
|
277
368
|
attachTo(player: IPlayer): ISubscription;
|
|
369
|
+
attachToUi(events: IUIEvents): Subscription;
|
|
370
|
+
attachToAds(adsEvents: IAdsEvents): ISubscription;
|
|
278
371
|
authorize(authToken?: string): Promise<unknown>;
|
|
279
372
|
pause(): void;
|
|
280
373
|
resume(): void;
|
|
281
374
|
destroy(): void;
|
|
282
375
|
resetViewSession(): void;
|
|
283
|
-
setFieldBlacklist(
|
|
376
|
+
setFieldBlacklist(): void;
|
|
284
377
|
logInited(): void;
|
|
285
378
|
logReady(payload: IReadyPayload): void;
|
|
286
|
-
logStarted(
|
|
379
|
+
logStarted(...args: Parameters<typeof this$1.logActionPlay>): void;
|
|
287
380
|
logPlay(): void;
|
|
288
381
|
logPause(payload: IPausePayload): void;
|
|
289
|
-
logSeek(): void;
|
|
382
|
+
logSeek(payload: ISeekPayload): void;
|
|
290
383
|
logFirstBytes(payload: IFirstBytesPayload): void;
|
|
291
384
|
logFirstFrame(payload: IFirstFramePayload): void;
|
|
292
385
|
logError(payload: IErrorPayload): void;
|
|
293
386
|
logWatchCoverageRecord(payload: IWatchCoveragePayload): void;
|
|
294
387
|
logWatchCoverageLive(payload: IWatchCoveragePayload): void;
|
|
295
388
|
logEmptyBuffer(payload: IEmptyBufferPayload): void;
|
|
296
|
-
logDownloadSpeed(
|
|
389
|
+
logDownloadSpeed(): void;
|
|
297
390
|
logAdSlotRequest(): void;
|
|
298
391
|
logAdStarted(sectionType: string): void;
|
|
299
392
|
logAdPaused(): void;
|
|
@@ -301,8 +394,13 @@ declare class OneStat implements IOneStat {
|
|
|
301
394
|
logAdEnded(): void;
|
|
302
395
|
logAdSkipped(): void;
|
|
303
396
|
logAdClicked(): void;
|
|
397
|
+
private subscribe;
|
|
398
|
+
private logPlayerReady;
|
|
399
|
+
private logActionPlay;
|
|
400
|
+
private logCloseAtEmptyBuffer;
|
|
401
|
+
private logActionStop;
|
|
304
402
|
private log;
|
|
305
403
|
private createLogItem;
|
|
306
404
|
}
|
|
307
405
|
|
|
308
|
-
export { ApiEnv, ConnectionType, ContentType, IOneStat, IStatContext, OneStat, Quality,
|
|
406
|
+
export { ApiEnv, ConnectionType, ContentType, IAdsEvents, IOneStat, IStatContext, IUIEvents, OneStat, Quality, SeekAction };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/videoplayer-statistics",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.35-dev.f578f79.0",
|
|
4
4
|
"author": "vk.com",
|
|
5
5
|
"description": "Statistics library for vk.com videoplayer",
|
|
6
6
|
"homepage": "https://vk.com",
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"**/*.d.ts"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@vkontakte/videoplayer-shared": "^1.0.
|
|
52
|
+
"@vkontakte/videoplayer-shared": "^1.0.24-dev.fd1a076.0",
|
|
53
53
|
"lodash": "4.17.21"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@vkontakte/videoplayer-core": "^2.0.
|
|
56
|
+
"@vkontakte/videoplayer-core": "^2.0.86-dev.f2e1ec4.0"
|
|
57
57
|
}
|
|
58
58
|
}
|