[{"data":1,"prerenderedAt":1033},["ShallowReactive",2],{"navigation":3,"post-\u002Fposts\u002F2024\u002Fget-video-rotation-by-mp4box-js":20,"surroundPosts-\u002Fposts\u002F2024\u002Fget-video-rotation-by-mp4box-js":1021},[4,8,12,16],{"title":5,"path":6,"stem":7},"首页","\u002F","00.index",{"title":9,"path":10,"stem":11},"文章","\u002Fposts","01.posts",{"title":13,"path":14,"stem":15},"动态","\u002Fmoments","02.moments",{"title":17,"path":18,"stem":19},"关于","\u002Fabout","09.about",{"id":21,"title":22,"body":23,"class":1001,"cover":1002,"coverSize":1001,"date":1003,"description":118,"draft":1004,"extension":1005,"hideComments":1004,"location":1001,"meta":1006,"navigation":323,"path":1007,"readingTime":1008,"seo":1013,"sitemap":1014,"stem":1015,"tags":1016,"time":1001,"weather":1001,"__hash__":1020},"posts\u002Fposts\u002F2024\u002F20240522.get-video-rotation-by-mp4box-js.md","MP4Box.js 获取视频旋转信息",{"type":24,"value":25,"toc":994},"minimark",[26,33,37,48,52,61,79,83,94,104,109,112,194,211,214,969,972,981,990],[27,28,29],"blockquote",{},[30,31,32],"p",{},"声明：本文部分内容使用 ChatGPT 生成",[34,35,36],"h2",{"id":36},"序言",[30,38,39,40,44,45,47],{},"公司的一个项目中用到 ",[41,42,43],"code",{},"MP4Box.js"," 在上传视频前去解析视频的宽高，并且根据宽高的比例做一些拦截，只允许 16:9 横屏的素材。后来发现一个问题，部分竖屏的素材也被提交上来了。经过研究，发现这类视频可能是由手机拍摄的，带了旋转信息，因此 ",[41,46,43],{}," 中的原始宽高有问题。",[34,49,51],{"id":50},"什么是-mp4boxjs","什么是 MP4Box.js",[30,53,54,60],{},[55,56,43],"a",{"href":57,"rel":58},"https:\u002F\u002Fgithub.com\u002Fgpac\u002Fmp4box.js",[59],"nofollow"," 是一个支持在浏览器中处理 MP4 文件的 JS 库，可以实现获取 MP4 文件的元数据信息、分割文件、提取媒体样本等高级处理能力。",[30,62,63,64,66,67,70,71,74,75,78],{},"通过 ",[41,65,43],{}," 可以从 ",[41,68,69],{},"videoTrack"," 中的 ",[41,72,73],{},"width"," 和 ",[41,76,77],{},"height"," 中获取视频的宽高，对于一般的视频都是 OK 的，但是带了旋转信息，通过 MP4Box 读出的宽高仍是旋转前的宽高，导致在一些场景下的判断会有问题。那么，如何获取到视频的旋转信息呢？",[34,80,82],{"id":81},"mp4boxjs-如何获取旋转信息","MP4Box.js 如何获取旋转信息",[30,84,85,86,89,90,93],{},"在 MP4 和 MOV 文件中，旋转信息通常存储在 ",[41,87,88],{},"tkhd"," (Track Header Box) 或 ",[41,91,92],{},"mvhd"," (Movie Header Box) 中。这个信息会影响视频轨道的显示方式。",[30,95,96,97,99,100,103],{},"Track Header Box (",[41,98,88],{},")：包含一个 ",[41,101,102],{},"matrix"," 的矩阵，描述视频帧的旋转。",[30,105,106,108],{},[41,107,102],{}," 字段中的旋转信息是通过一个 3x3 矩阵来表示的，具体可以参考 ISO\u002FIEC 14496-12 标准。",[30,110,111],{},"具体实现代码：",[113,114,119],"pre",{"className":115,"code":116,"language":117,"meta":118,"style":118},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","Math.atan2(videoTrack.matrix[1], videoTrack.matrix[0]) * (180 \u002F Math.PI)\n","ts","",[41,120,121],{"__ignoreMap":118},[122,123,126,130,134,138,141,143,146,150,153,156,159,161,163,166,169,173,176,179,182,185,187,191],"span",{"class":124,"line":125},"line",1,[122,127,129],{"class":128},"su5hD","Math",[122,131,133],{"class":132},"sP7_E",".",[122,135,137],{"class":136},"sGLFI","atan2",[122,139,140],{"class":128},"(videoTrack",[122,142,133],{"class":132},[122,144,145],{"class":128},"matrix[",[122,147,149],{"class":148},"srdBf","1",[122,151,152],{"class":128},"]",[122,154,155],{"class":132},",",[122,157,158],{"class":128}," videoTrack",[122,160,133],{"class":132},[122,162,145],{"class":128},[122,164,165],{"class":148},"0",[122,167,168],{"class":128},"]) ",[122,170,172],{"class":171},"smGrS","*",[122,174,175],{"class":128}," (",[122,177,178],{"class":148},"180",[122,180,181],{"class":171}," \u002F",[122,183,184],{"class":128}," Math",[122,186,133],{"class":132},[122,188,190],{"class":189},"s_hVV","PI",[122,192,193],{"class":128},")\n",[30,195,196,197,200,201,203,204,207,208,210],{},"其中，",[41,198,199],{},"Math.atan2"," 是 JS 中的一个数学函数，用于计算从点 (0, 0) 到点 (x, y) 之间的直线与 x 轴正方向之间的角度，角度的单位为弧度。这个函数能够处理所有的象限，因此可以返回从 -π 到 π 之间的值。",[41,202,199],{}," 函数在计算几何、游戏开发、图形编程以及需要处理极坐标转换等场景中非常有用。与 ",[41,205,206],{},"Math.atan"," 不同，",[41,209,199],{}," 可以处理 (x, y) 都为零的情况，并根据 x 和 y 的符号确定正确的象限。",[34,212,213],{"id":213},"完整实现代码",[113,215,217],{"className":115,"code":216,"language":117,"meta":118,"style":118},"function getVideoMetaInfo(file: File): Promise\u003Cany> {\n  return new Promise((resolve, reject) => {\n    const mp4boxFile = MP4Box.createFile()\n\n    mp4boxFile.onReady = function (info: any) {\n      if (info && info.videoTracks?.length) {\n        const videoTrack = info.videoTracks[0]\n        const result = {\n          duration: videoTrack.duration \u002F videoTrack.timescale,\n          codec: videoTrack.codec,\n          fps: videoTrack.nb_samples \u002F (videoTrack.duration \u002F videoTrack.timescale),\n          width: videoTrack.video.width,\n          height: videoTrack.video.height,\n          rotation: Math.atan2(videoTrack.matrix[1], videoTrack.matrix[0]) * (180 \u002F Math.PI),\n        }\n\n        resolve(result)\n      }\n    }\n\n    mp4boxFile.onError = function (info: any) {\n      console.error('mp4box.js error', info)\n      reject(info)\n    }\n\n    const reader = file.stream().getReader()\n    let offset = 0\n    reader.read().then(function getNextChunk({ done, value }: any) {\n      if (done) {\n        mp4boxFile.flush()\n        return\n      }\n\n      const copy = value.buffer\n      copy.fileStart = offset\n      offset += value.length\n      mp4boxFile.appendBuffer(copy)\n      reader.read().then(getNextChunk)\n    })\n  })\n}\n",[41,218,219,263,295,318,325,355,388,412,424,451,468,505,526,546,606,612,617,630,636,642,647,673,702,714,719,724,752,766,813,827,840,846,851,856,874,890,906,924,947,955,963],{"__ignoreMap":118},[122,220,221,225,228,231,235,238,242,245,247,250,253,257,260],{"class":124,"line":125},[122,222,224],{"class":223},"sbsja","function",[122,226,227],{"class":136}," getVideoMetaInfo",[122,229,230],{"class":132},"(",[122,232,234],{"class":233},"s99_P","file",[122,236,237],{"class":171},":",[122,239,241],{"class":240},"sbgvK"," File",[122,243,244],{"class":132},")",[122,246,237],{"class":171},[122,248,249],{"class":240}," Promise",[122,251,252],{"class":132},"\u003C",[122,254,256],{"class":255},"sZMiF","any",[122,258,259],{"class":132},">",[122,261,262],{"class":132}," {\n",[122,264,266,270,273,275,278,280,283,285,288,290,293],{"class":124,"line":265},2,[122,267,269],{"class":268},"sVHd0","  return",[122,271,272],{"class":171}," new",[122,274,249],{"class":255},[122,276,230],{"class":277},"skxfh",[122,279,230],{"class":132},[122,281,282],{"class":233},"resolve",[122,284,155],{"class":132},[122,286,287],{"class":233}," reject",[122,289,244],{"class":132},[122,291,292],{"class":223}," =>",[122,294,262],{"class":132},[122,296,298,301,304,307,310,312,315],{"class":124,"line":297},3,[122,299,300],{"class":223},"    const",[122,302,303],{"class":189}," mp4boxFile",[122,305,306],{"class":171}," =",[122,308,309],{"class":128}," MP4Box",[122,311,133],{"class":132},[122,313,314],{"class":136},"createFile",[122,316,317],{"class":277},"()\n",[122,319,321],{"class":124,"line":320},4,[122,322,324],{"emptyLinePlaceholder":323},true,"\n",[122,326,328,331,333,336,338,341,343,346,348,351,353],{"class":124,"line":327},5,[122,329,330],{"class":128},"    mp4boxFile",[122,332,133],{"class":132},[122,334,335],{"class":136},"onReady",[122,337,306],{"class":171},[122,339,340],{"class":223}," function",[122,342,175],{"class":132},[122,344,345],{"class":233},"info",[122,347,237],{"class":171},[122,349,350],{"class":255}," any",[122,352,244],{"class":132},[122,354,262],{"class":132},[122,356,358,361,363,365,368,371,373,376,379,382,385],{"class":124,"line":357},6,[122,359,360],{"class":268},"      if",[122,362,175],{"class":277},[122,364,345],{"class":128},[122,366,367],{"class":171}," &&",[122,369,370],{"class":128}," info",[122,372,133],{"class":132},[122,374,375],{"class":128},"videoTracks",[122,377,378],{"class":132},"?.",[122,380,381],{"class":189},"length",[122,383,384],{"class":277},") ",[122,386,387],{"class":132},"{\n",[122,389,391,394,396,398,400,402,404,407,409],{"class":124,"line":390},7,[122,392,393],{"class":223},"        const",[122,395,158],{"class":189},[122,397,306],{"class":171},[122,399,370],{"class":128},[122,401,133],{"class":132},[122,403,375],{"class":128},[122,405,406],{"class":277},"[",[122,408,165],{"class":148},[122,410,411],{"class":277},"]\n",[122,413,415,417,420,422],{"class":124,"line":414},8,[122,416,393],{"class":223},[122,418,419],{"class":189}," result",[122,421,306],{"class":171},[122,423,262],{"class":132},[122,425,427,430,432,434,436,439,441,443,445,448],{"class":124,"line":426},9,[122,428,429],{"class":277},"          duration",[122,431,237],{"class":132},[122,433,158],{"class":128},[122,435,133],{"class":132},[122,437,438],{"class":128},"duration",[122,440,181],{"class":171},[122,442,158],{"class":128},[122,444,133],{"class":132},[122,446,447],{"class":128},"timescale",[122,449,450],{"class":132},",\n",[122,452,454,457,459,461,463,466],{"class":124,"line":453},10,[122,455,456],{"class":277},"          codec",[122,458,237],{"class":132},[122,460,158],{"class":128},[122,462,133],{"class":132},[122,464,465],{"class":128},"codec",[122,467,450],{"class":132},[122,469,471,474,476,478,480,483,485,487,489,491,493,495,497,499,501,503],{"class":124,"line":470},11,[122,472,473],{"class":277},"          fps",[122,475,237],{"class":132},[122,477,158],{"class":128},[122,479,133],{"class":132},[122,481,482],{"class":128},"nb_samples",[122,484,181],{"class":171},[122,486,175],{"class":277},[122,488,69],{"class":128},[122,490,133],{"class":132},[122,492,438],{"class":128},[122,494,181],{"class":171},[122,496,158],{"class":128},[122,498,133],{"class":132},[122,500,447],{"class":128},[122,502,244],{"class":277},[122,504,450],{"class":132},[122,506,508,511,513,515,517,520,522,524],{"class":124,"line":507},12,[122,509,510],{"class":277},"          width",[122,512,237],{"class":132},[122,514,158],{"class":128},[122,516,133],{"class":132},[122,518,519],{"class":128},"video",[122,521,133],{"class":132},[122,523,73],{"class":128},[122,525,450],{"class":132},[122,527,529,532,534,536,538,540,542,544],{"class":124,"line":528},13,[122,530,531],{"class":277},"          height",[122,533,237],{"class":132},[122,535,158],{"class":128},[122,537,133],{"class":132},[122,539,519],{"class":128},[122,541,133],{"class":132},[122,543,77],{"class":128},[122,545,450],{"class":132},[122,547,549,552,554,556,558,560,562,564,566,568,570,572,574,576,578,580,582,584,586,588,590,592,594,596,598,600,602,604],{"class":124,"line":548},14,[122,550,551],{"class":277},"          rotation",[122,553,237],{"class":132},[122,555,184],{"class":128},[122,557,133],{"class":132},[122,559,137],{"class":136},[122,561,230],{"class":277},[122,563,69],{"class":128},[122,565,133],{"class":132},[122,567,102],{"class":128},[122,569,406],{"class":277},[122,571,149],{"class":148},[122,573,152],{"class":277},[122,575,155],{"class":132},[122,577,158],{"class":128},[122,579,133],{"class":132},[122,581,102],{"class":128},[122,583,406],{"class":277},[122,585,165],{"class":148},[122,587,168],{"class":277},[122,589,172],{"class":171},[122,591,175],{"class":277},[122,593,178],{"class":148},[122,595,181],{"class":171},[122,597,184],{"class":128},[122,599,133],{"class":132},[122,601,190],{"class":189},[122,603,244],{"class":277},[122,605,450],{"class":132},[122,607,609],{"class":124,"line":608},15,[122,610,611],{"class":132},"        }\n",[122,613,615],{"class":124,"line":614},16,[122,616,324],{"emptyLinePlaceholder":323},[122,618,620,623,625,628],{"class":124,"line":619},17,[122,621,622],{"class":136},"        resolve",[122,624,230],{"class":277},[122,626,627],{"class":128},"result",[122,629,193],{"class":277},[122,631,633],{"class":124,"line":632},18,[122,634,635],{"class":132},"      }\n",[122,637,639],{"class":124,"line":638},19,[122,640,641],{"class":132},"    }\n",[122,643,645],{"class":124,"line":644},20,[122,646,324],{"emptyLinePlaceholder":323},[122,648,650,652,654,657,659,661,663,665,667,669,671],{"class":124,"line":649},21,[122,651,330],{"class":128},[122,653,133],{"class":132},[122,655,656],{"class":136},"onError",[122,658,306],{"class":171},[122,660,340],{"class":223},[122,662,175],{"class":132},[122,664,345],{"class":233},[122,666,237],{"class":171},[122,668,350],{"class":255},[122,670,244],{"class":132},[122,672,262],{"class":132},[122,674,676,679,681,684,686,690,694,696,698,700],{"class":124,"line":675},22,[122,677,678],{"class":128},"      console",[122,680,133],{"class":132},[122,682,683],{"class":136},"error",[122,685,230],{"class":277},[122,687,689],{"class":688},"sjJ54","'",[122,691,693],{"class":692},"s_sjI","mp4box.js error",[122,695,689],{"class":688},[122,697,155],{"class":132},[122,699,370],{"class":128},[122,701,193],{"class":277},[122,703,705,708,710,712],{"class":124,"line":704},23,[122,706,707],{"class":136},"      reject",[122,709,230],{"class":277},[122,711,345],{"class":128},[122,713,193],{"class":277},[122,715,717],{"class":124,"line":716},24,[122,718,641],{"class":132},[122,720,722],{"class":124,"line":721},25,[122,723,324],{"emptyLinePlaceholder":323},[122,725,727,729,732,734,737,739,742,745,747,750],{"class":124,"line":726},26,[122,728,300],{"class":223},[122,730,731],{"class":189}," reader",[122,733,306],{"class":171},[122,735,736],{"class":128}," file",[122,738,133],{"class":132},[122,740,741],{"class":136},"stream",[122,743,744],{"class":277},"()",[122,746,133],{"class":132},[122,748,749],{"class":136},"getReader",[122,751,317],{"class":277},[122,753,755,758,761,763],{"class":124,"line":754},27,[122,756,757],{"class":223},"    let",[122,759,760],{"class":128}," offset",[122,762,306],{"class":171},[122,764,765],{"class":148}," 0\n",[122,767,769,772,774,777,779,781,784,786,788,791,794,797,799,802,805,807,809,811],{"class":124,"line":768},28,[122,770,771],{"class":128},"    reader",[122,773,133],{"class":132},[122,775,776],{"class":136},"read",[122,778,744],{"class":277},[122,780,133],{"class":132},[122,782,783],{"class":136},"then",[122,785,230],{"class":277},[122,787,224],{"class":223},[122,789,790],{"class":136}," getNextChunk",[122,792,793],{"class":132},"({",[122,795,796],{"class":233}," done",[122,798,155],{"class":132},[122,800,801],{"class":233}," value",[122,803,804],{"class":132}," }",[122,806,237],{"class":171},[122,808,350],{"class":255},[122,810,244],{"class":132},[122,812,262],{"class":132},[122,814,816,818,820,823,825],{"class":124,"line":815},29,[122,817,360],{"class":268},[122,819,175],{"class":277},[122,821,822],{"class":128},"done",[122,824,384],{"class":277},[122,826,387],{"class":132},[122,828,830,833,835,838],{"class":124,"line":829},30,[122,831,832],{"class":128},"        mp4boxFile",[122,834,133],{"class":132},[122,836,837],{"class":136},"flush",[122,839,317],{"class":277},[122,841,843],{"class":124,"line":842},31,[122,844,845],{"class":268},"        return\n",[122,847,849],{"class":124,"line":848},32,[122,850,635],{"class":132},[122,852,854],{"class":124,"line":853},33,[122,855,324],{"emptyLinePlaceholder":323},[122,857,859,862,865,867,869,871],{"class":124,"line":858},34,[122,860,861],{"class":223},"      const",[122,863,864],{"class":189}," copy",[122,866,306],{"class":171},[122,868,801],{"class":128},[122,870,133],{"class":132},[122,872,873],{"class":128},"buffer\n",[122,875,877,880,882,885,887],{"class":124,"line":876},35,[122,878,879],{"class":128},"      copy",[122,881,133],{"class":132},[122,883,884],{"class":128},"fileStart",[122,886,306],{"class":171},[122,888,889],{"class":128}," offset\n",[122,891,893,896,899,901,903],{"class":124,"line":892},36,[122,894,895],{"class":128},"      offset",[122,897,898],{"class":171}," +=",[122,900,801],{"class":128},[122,902,133],{"class":132},[122,904,905],{"class":189},"length\n",[122,907,909,912,914,917,919,922],{"class":124,"line":908},37,[122,910,911],{"class":128},"      mp4boxFile",[122,913,133],{"class":132},[122,915,916],{"class":136},"appendBuffer",[122,918,230],{"class":277},[122,920,921],{"class":128},"copy",[122,923,193],{"class":277},[122,925,927,930,932,934,936,938,940,942,945],{"class":124,"line":926},38,[122,928,929],{"class":128},"      reader",[122,931,133],{"class":132},[122,933,776],{"class":136},[122,935,744],{"class":277},[122,937,133],{"class":132},[122,939,783],{"class":136},[122,941,230],{"class":277},[122,943,944],{"class":128},"getNextChunk",[122,946,193],{"class":277},[122,948,950,953],{"class":124,"line":949},39,[122,951,952],{"class":132},"    }",[122,954,193],{"class":277},[122,956,958,961],{"class":124,"line":957},40,[122,959,960],{"class":132},"  }",[122,962,193],{"class":277},[122,964,966],{"class":124,"line":965},41,[122,967,968],{"class":132},"}\n",[34,970,971],{"id":971},"后记",[30,973,974,975,980],{},"在解决这个问题的过程中，我发现另一个强大的 JS 库：",[55,976,979],{"href":977,"rel":978},"https:\u002F\u002Fgithub.com\u002Fbuzz\u002Fmediainfo.js",[59],"mediainfo.js","，已经帮我们做好了这一切，并且支持解析更多格式的文件。",[30,982,983,984,989],{},"我基于这个库，做了一个可视化的工具页：",[55,985,988],{"href":986,"rel":987},"https:\u002F\u002Ftools.yuanfen.net\u002Fmetadata",[59],"媒体文件元数据解析","，方便解析媒体文件的元数据，纯浏览器本地解析，性能优异，并且不需要读完整个文件，读完头就可以了。",[991,992,993],"style",{},"html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":118,"searchDepth":265,"depth":265,"links":995},[996,997,998,999,1000],{"id":36,"depth":265,"text":36},{"id":50,"depth":265,"text":51},{"id":81,"depth":265,"text":82},{"id":213,"depth":265,"text":213},{"id":971,"depth":265,"text":971},null,"jpg","2024-05-22",false,"md",{},"\u002Fposts\u002F2024\u002Fget-video-rotation-by-mp4box-js",{"text":1009,"minutes":1010,"time":1011,"words":1012},"4 min read",3.68,220800,736,{"title":22,"description":118},{"loc":1007},"posts\u002F2024\u002F20240522.get-video-rotation-by-mp4box-js",[1017,1018,1019],"技术","前端","音视频处理","D0zmDUaMjME7E7unN1UVePE8EFtBxbFmdtpj9iS2Dlc",[1022,1027],{"title":1023,"path":1024,"stem":1025,"date":1026,"description":118,"children":-1},"W3C 技术分享 —— 《前端在数字人创作工具中的应用实践》","\u002Fposts\u002F2024\u002Fwebvolve-series-events-speech","posts\u002F2024\u002F20240529.webvolve-series-events-speech","2024-05-29",{"title":1028,"path":1029,"stem":1030,"date":1031,"description":1032,"children":-1},"记录一次 WordPress 被恶意代码注入的问题","\u002Fposts\u002F2024\u002Fwordpress-hacked","posts\u002F2024\u002F20240327.wordpress-hacked","2024-03-27","今天发现之前帮一个客户维护的服务器流量近期一直比较高，是平常的几十倍。看了下请求，都是一些奇奇怪怪的 URL，并且甚至还能返回 200。访问看了下，是一些别的产品的营销页，看了下请求来源，也都是一些营销机器人。",1777579137513]