Skip to content
Ling-LAPublic

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

IwaraFlow

Android 原生的 Iwara 竖屏短视频流播放器,提供类似短视频 App 的连续浏览体验。

0.16.2 更新

  • 关闭「点一下画面暂停播放」时,暂停后仍可单击画面切换作者 / 点赞收藏栏与播放控制栏,保持暂停;开启该选项时保留原有单击暂停 / 继续播放行为。

  • 查看操作引导时暂停视频并保留当前画面和进度。

  • 从设置打开操作引导时,临时回到原视频播放页;关闭引导或按返回键后回到设置,保留未保存的设置与滚动位置。

  • 切换横屏 / 竖屏引导时同步旋转实际窗口和播放器布局,按当前窗口方向绘制指引。结束后恢复原全屏状态和屏幕方向,不消耗首次横屏引导。

0.16.1 更新

  • 修正普通播放操作指引:虚线框避开顶部导航、右侧按钮和底部作者 / 标题 / 进度控件,标明按钮区独立操作;文字跟随实际可用区域布局,不再跨入控件区域。
  • 指引仍使用真实播放卡片的三等分边界,不因避让控件改变长按区域。加载视频后自动更新避让范围;2.5 秒双连与首次横屏引导规则保持一致。

0.16.0 更新

  • 双连统一为按住 2.5 秒:普通播放及竖屏全屏按上 / 中 / 下分别执行不感兴趣、点赞+收藏、2× 加速;横屏全屏按左 / 中 / 右执行。控件独立响应,松手或移动取消双连,红黄双环同步绘制。
  • 首次启动展示普通 / 竖屏共用引导;竖屏视频进入全屏不自动弹引导,也不消耗首次横屏全屏引导。
  • 小窗去掉按钮背后的灰色方块,采用圆角窗口和透明图标。静置 3 秒隐藏控件,轻触画面切换显示,拖动仍只移动小窗;启用屏幕阅读器时保留可访问的控件。
  • 全局请求按播放、交互、后台任务分配并发名额,优先处理当前播放;登录令牌刷新合并,旧账号请求不能恢复退出后的会话。退出 Iwara 登录保留翻译服务密钥。
  • 推荐改用平滑且有上限的抽样权重,召回轮换覆盖整个兴趣池;系统标签参考独立视频 / 作者证据,并按标签数量分摊正向加分,降低单一内容占满推荐的机会。减少推荐与主动屏蔽分开,支持撤销屏蔽。
  • 收藏 / 历史分页读取,增加本地搜索和时间排序;搜索保留已取回候选、取消过期请求,支持调整多语言匹配词或仅按原文搜索。
  • 预加载增加网速、播放缓冲和剩余存储检查,移动 / 计量网络可单独设置。网络不佳只停止后续视频预加载,当前视频继续缓存;空间不足时继续在线播放。
  • 弹幕缓存文字宽度,暂停、隐藏或关闭时停止连续重绘,支持设置同时显示行数。编辑表单时,剪贴板链接改为可点击提示,避免打断输入。
  • 上传增加后台前台服务、进度通知、暂停和任务入口,加密保存草稿及处理进度。已上传完成的文件可继续查询处理;发布结果不确定时先检查作品,不自动重复投稿。
  • 新增「数据与存储」:清理闲置视频缓存、导入 / 导出收藏与当前兴趣、清除历史、重置系统画像,以及可选按账号隔离兴趣。另可关闭浏览及推荐行为记录;显式收藏仍保留。
  • 统一页面浅色 / 深色样式,增加播放无障碍操作、主页播放状态恢复与本机性能诊断;诊断导出脱敏,不自动上传。

实现范围、验证方式与限制见 0.16.0 优化记录。

0.15.1 更新

  • 全屏播放按视频方向提供三段长按:横屏左侧不感兴趣、中间按住 3 秒点赞+收藏、右侧 2× 加速;竖屏对应上 / 中 / 下。双连从按下开始在按住的位置居中显示更大的红 / 黄双环,松开、移动、切换视频或模式会取消。全屏不单独显示点赞或收藏按钮,任意区域双击仍可点赞。

  • 普通模式长按点赞或收藏按钮时,两者同步从顶部顺时针画圆,按满 3 秒完成双连。

  • 横屏不感兴趣面板改为左侧限宽滚动面板,保留视频画面;首次进入横屏 / 竖屏全屏时展示操作引导,设置内可重新查看。

  • 兴趣管理统一从设置进入,移除各播放菜单的重复入口。修复粉丝关系解析,恢复头像、名称、个人主页跳转及资料补全,粉丝卡片不再误标“已关注”。

  • 弹幕改为从右向左滚动,避开顶部导航、返回菜单和弱网提示。

  • 兴趣管理顶部固定手动 / 系统 / 已屏蔽分区,默认显示手动兴趣;标签双列展示,支持系统标签搜索和每次 24 项展开。

  • 我的主页与作者页共用头部及作品列表,关注 / 粉丝 / 收藏改为横排圆角按钮,右上角为深蓝色「上传」;修复空简介显示 null 和空作品提示重复。

  • 上传改为应用内原生表单,复用现有登录,直接上传视频文件并提交标题、简介、标签、分级和可见范围。显示传输和官网处理进度,失败后可重试;发布结果未知时先确认我的作品,避免重复投稿。协议依据官网公开客户端核实,详见 视频上传协议;未使用真实账号发布测试视频。

  • 上传页底部展示创作者须知、格式与码率要求,以及从官网读取的中文规则;规则可展开阅读、重试加载并缓存,保留官网原文入口。

  • 首次打开应用且未授权时说明并引导开启悬浮窗;拒绝或关闭后不再自动询问,仍可从小窗入口手动授权。

0.15.0 更新

  • 作者作品列表显示上传日期;视频分享文字统一为标题、作者、链接。
  • 点赞或收藏按钮按住 3 秒,以按钮颜色从顶部顺时针画圆,完成后点赞并收藏;提前松手、移动或切换视频取消双连,已点赞或收藏不会被取消。
  • 播放持续缓冲或发生网络错误时提示降低画质,点击降低一级并保留播放位置。
  • 当前视频持续尝试完整缓存,弱网也继续;后续预加载默认开启,可在设置关闭。当前连续缓存超过 40% 且播放稳定 6 秒、缓冲余量充足才启动下一条;当前完成且下一条超过 40% 后允许第三条。弱网只取消后续预加载。播放进度条灰色层显示缓存进度。旧缓存按 2 GiB 预算淘汰,当前及正在预加载的视频受到保护,可暂时超过该预算;设备空间不足时回退到正常在线播放。
  • 兴趣管理分系统分析和手动偏好。系统标签/作者分数限制在 −6~8,长期分数每 30 天折半,同一视频同一动作每天最多记 3 次;系统标签可忽略、恢复或调整为 25% / 50% / 100% / 150%,调整后仍受上限约束。手动正向只额外加 1.5 分,负向只额外减 3 分,不随时间/热度叠加。候选按有界权重抽样,未主动屏蔽的负向内容保留机会。兴趣设置不影响搜索。
  • 推荐理由新增「猜你喜欢」,根据点赞、收藏、关注及完整观看的正向信号判断。
  • 简介/评论旁新增「弹幕」页签,默认将当前视频评论从左向右滚动,可即时调整开关、字号、透明度、速度和上半屏/下半屏/全屏位置。
  • 设置与兴趣管理改为独立页面,使用作者主页同款浅蓝背景和白色圆角分组。主菜单「我的」集中个人资料、上传作品、关注、粉丝和收藏。
  • 「上传视频」在统一页面框架内接入 Iwara 官网表单与系统文件选择器,标题、简介、标签和文件直接由官网提交;官网登录与应用 API 登录独立。本版本不实现未经核实的私有视频上传 API,也未进行真实投稿测试。
  • 小窗支持左上返回软件、右上关闭、底部中间播放/暂停,可拖动。需要 Android 悬浮窗授权;未授权可选择系统画中画,其按钮布局由系统决定。
  • 作者、收藏、历史等视频列表的播放页右上角新增页面菜单,含「回到主页」,可直接回到推荐页。
  • Android 12+ 先检查剪贴板元数据的 URL 分类,跳过普通文字和未完成分类的内容,再读取最新一条复制内容;同一次复制仍只打开一次。Android 不提供可免读取判断 URL 域名的接口,因此非 Iwara 网址仍可能出现系统读取提示;无法分类的链接不会自动打开。

验证包含单元回归、发布构建,以及 CI 的 Android 16 返回路径测试。真实账号投稿、厂商悬浮窗权限界面和公网弱网播放仍需设备验证。

0.14.2 更新

  • 修复手动添加感兴趣标签后,同类内容挤占推荐的问题:手动兴趣只提供有上限的加分,不按命中标签数累加。
  • 存在可用的其他候选时,连续 3 条手动兴趣内容后保留其他内容的机会;首次推荐、续页重排和推荐回退均沿用此规则,不强行插入已屏蔽或手动不感兴趣的内容。
  • 兴趣偏好继续只影响推荐,不影响主动搜索。

0.14.1 更新

  • 剪贴板跳转:复制 Iwara 视频或作者主页链接后打开应用,即可进入对应页面。设置 → 分享链接中可关闭,默认开启。只识别当前最新一条复制内容,同一次复制只打开一次,重启应用也不重复;再次复制同一链接后可以重新打开。
  • 分享视频接续推荐:分享视频保留在首条,上划继续浏览正常推荐。
  • 分享文案:视频发布时间只显示年月日;作者分享采用「作者:某某」及另起一行的主页链接。

0.14.0 更新

  • 兴趣管理 → 主动调整兴趣:添加、切换或移除感兴趣/不感兴趣标签。主动偏好长期保存在本机,分别提高或降低推荐机会;负偏好不等于屏蔽,且均不影响搜索。此前长按产生的屏蔽仍可在同一界面恢复。
  • 多关键词 AND:空格、逗号或分号分隔的关键词必须全部命中。同一关键词的不同语言写法为等价选项,支持混合语言命中;带空格的完整标签可用下划线或双引号输入。
  • 严格搜索字段:视频名只核对标题,标签只核对完整标签,作者只核对名称和用户名。服务端宽泛结果在播放源检查之前过滤。领域词优先使用内置别名,避免将“扶她”错译为“Support Her”,也不把“futa”扩展为“双性恋”。其他词继续按翻译设置补充语言写法。
  • 分享视频:包含标题、作者、发布时间(含时区)和链接;缺失信息明确显示为未知。
  • 全屏下载:全屏控制行的小窗按钮右侧增加下载按钮,沿用清晰度选择及各页面现有下载流程。

搜索排序作用于已加载且匹配的结果;遇到过滤后暂时为空的页面,可点击状态栏继续搜索后续页。

功能

视频流

  • 四个版块:推荐 / 最新 / 流行 / 人气
    • 最新:Iwara 官方 sort=date
    • 流行:Iwara 官方 sort=trending
    • 人气:Iwara 官方 sort=popularity
    • 推荐:本地推荐算法,见下文
  • 上滑下一条、下滑上一条,滑到末尾自动加载更多;推荐页翻页继续使用推荐候选,候选用完重新生成
  • 播放结束自动进入下一条(可关闭)
  • 刷新推荐时排除已看视频:只在生成新的推荐列表时过滤,不在滑动过程中自动跳过
  • 可播放验证:视频进入列表前先解析实际 CDN 播放源并做 Range 探测,确认能返回媒体数据才显示
  • 首屏边验证边上屏:最先通过验证的几条立即播放,其余在后台继续验证并按原顺序补入列表
  • 单条视频源和单个榜单请求都有时间预算,不会拖住整页

播放器

  • AndroidX Media3 / ExoPlayer,默认最高可用画质,可手动切换清晰度
  • 单击播放 / 暂停,可在设置里关掉(「点一下画面暂停播放」,默认开)
    • 关掉后点一下画面只在两套界面之间切换:标题 / 标签 / 操作栏 ↔ 进度条 / 快进后退 / 剩余时长 / 小窗,视频照常播
    • 这时控制行里的按钮是暂停图标,点它才暂停;暂停着的时候仍是播放三角。全屏、作者页、搜索页、收藏 / 已下载的播放流都一样
    • 划到下一条、卡片被回收复用、或在设置里把开关打开,点出来的控件都会收起
  • 暂停时在视频标签下方显示可拖动的进度条,同时隐藏信息栏和操作栏;播放时恢复。进度条右上方显示剩余时长(-m:ss),拖动时屏幕下方居中显示“当前位置 / 总时长”
  • 暂停时进度条上方、左下角显示控制行:后退 N 秒 / 播放三角 / 前进 N 秒。N 在设置中选择(5 / 10 / 15 / 30 / 60,默认 15),播放三角可在设置里关闭
  • 横屏视频画面略高于屏幕中央(抬起卡片高度的 24%),竖屏视频铺满
  • 长按非控件播放区域分为三段:普通模式和竖屏全屏为上 / 中 / 下,横屏全屏为左 / 中 / 右,依次是不感兴趣选项、按住 2.5 秒点赞+收藏、临时 2× 加速。提前松手或移动取消双连,加速松手恢复;全屏任意位置双击点赞。
  • 按住画面左右滑动调进度:位移占屏宽的比例取 1.8 次方乘可调范围——十分之一屏约 5 秒的微调,划满一屏是整个可调范围(片长和 5 分钟里小的那个)。画面跟着手指走(拖动中跳到最近的关键帧,松手再精确定位;位置变化不足 250ms 不重新定位),屏幕下方的胶囊里显示“当前位置 / 总时长 ±偏移”(普通模式离底边 150dp 让开信息栏,全屏时下移到 56dp)。全屏时同样可用
  • 全屏:操作栏的全屏按钮收起所有控件让画面铺满;横屏视频顺便转到横屏,竖屏视频只收控件不转屏。全屏中暂停会显示进度条、快进 / 后退、剩余时长、小窗和退出全屏;退出全屏后接着播,信息栏和操作栏随之回来;返回键先退出全屏
  • 小窗按钮移到暂停时进度条右上方那一行(和剩余时长同一行);“切到后台自动进入画中画”的设置不变
  • 点赞 / 收藏 / 双击点赞的动画播在点击的位置:按钮上或手指落点
  • 画中画(PiP),可设置切到后台自动进入
  • 分享:应用内分享面板列出能接收链接的应用,点选后直接拉起该应用的分享入口(QQ 等应用以自己的小窗卡片盖在视频上,视频继续播放);另有复制链接和系统选择器
  • 播放地址过期或出错时自动重新解析并从原位置继续,最多重试 2 次
  • 播放卡死看门狗:时间轴长时间不前进时自动重建播放源
  • 全 App 单一播放所有权:进入其它视频页面时立即停止上一页面的播放器

简介与评论

  • 底部半屏面板有「简介」「评论」「弹幕」三个页签:点视频标题或标签行打开简介,点右侧评论按钮打开评论;主页、作者页、搜索页、收藏 / 已下载 / 历史的播放流都有
  • 页签并排放在一起,手指横向拖动时跟着手指走、松手顺滑地滑到目标页(划过容器宽度的 28% 或甩得够快就换页),点页签也是滑过去
  • 简介页显示标题、作者、日期、播放 / 点赞数、标签和作者写的正文;本地列表里没带简介的视频打开时补拉一次详情
  • 简介页的每个标签都能点,点了直接去搜这个标签(落在搜索页的「标签」那一栏),并记一笔兴趣
  • 自动翻译:面板打开时,外语的简介和评论自动翻成中文,正文上方一行小字标明“翻译自 × 语”(服务没报源语言时按文字的文字系统和常见功能词猜;猜不出只写“已翻译”),点它切回原文。原文已是中文或没有文字(纯表情、数字)的不翻、不显示这一行;翻译失败在同一位置显示原因,点击重试。面板没打开时不发请求,结果按原文缓存,同一条不会翻第二次
  • 翻译服务可选(设置 → 翻译):默认谷歌翻译免费网页接口(translate_a/single,无需密钥);内置 DeepL(免费版 Key 自动走 api-free)、微软 Azure Translator(Key + 区域)、百度翻译开放平台(APP ID + 密钥,MD5 签名)、LibreTranslate(服务器地址 + 可选 Key)、AI 翻译(内置 OpenAI、DeepSeek、通义千问、Kimi、智谱 GLM、硅基流动、Gemini、xAI、OpenRouter 九家服务商,接口地址和模型已预设,只需填 API Key;选“自定义”可接任何兼容 OpenAI 聊天接口的中转站:地址写到 /v1 即可自动补成 /chat/completions,模型默认 gpt-4o-mini。请求不带 temperature 等采样参数,推理类模型也能用;失败原因写入诊断信息);也可以自定义接口:地址模板({text}、{target} 占位)、GET / POST、请求体模板、请求头、译文和源语言的字段路径(data.translations.0.text 这样的点分路径,留空按常见字段名猜)。换服务后翻译缓存清空
  • 右侧操作栏的评论按钮打开评论页签,内容为 Iwara 官方评论
  • 支持回复:发送到 Iwara 官网,与网页端回复等价;「共 N 条回复」原地展开 / 收起
  • 面板顶边对齐画面底边:横屏视频面板接在画面下方,竖屏视频画面按比例缩到顶栏与面板之间
  • 面板打开时播放不受影响;点击画面、翻页、返回键、进入小窗均关闭面板;按住顶部把手下拖也可收起
  • 写评论时输入层贴在键盘上方、盖在面板之上,页面和面板不收缩;点空白处收起键盘,未发送的文字保留为草稿
  • 未登录时点输入框会先弹出登录框
  • 点评论者的头像或名字进入其主页;没有作品的用户只显示资料,作品列表标明“没有作品”

作者主页 / 关注 / 好友

  • 点击作者名进入作者主页,分页展示该作者作品并显示真实缩略图
  • 简介默认显示三行,点击展开全文,滑动作品列表时收起
  • 列表先显示,可播放性后台验:作品元数据一回来就出列表,不用等整页 36 条都探测完(弱网上那是干等好几秒);验证结果回来再更新卡片
  • 不可播放的作品保留在列表中,并在缩略图上标出原因(仅限好友 / 无权限 / 处理中 / 资源失效);还没验到的照常能点开,只有确定播不了的才拦住并说明原因
  • 点击可播放作品后进入仅包含该作者作品的竖滑播放流;滑到最后一条再往上拉、或最后一条播完时提示“没有更多视频了”,不绕回开头
  • 主菜单的浏览历史 / 我的收藏 / 已下载同样是列表 + 竖滑播放流:点一条从它开始播,上滑是列表里的下一条,到底有同样的提示;已下载的直接放本地文件,其它在线播放;评论、简介、小窗、分享、下载与作者页播放流一致
  • 返回顺序:作者播放流 → 作者作品列表 → 进入作者页的页面;系统返回键、全面屏手势和页面按钮共用同一逻辑
  • 关注 / 取消关注,好友申请 / 取消申请 / 删除好友,状态与 Iwara 官方同步
  • 主菜单「已关注用户」按服务端总数翻页读取,关注数超过 50 也会全部列出
  • 作者主页可分享作者名字、简介和主页链接

Iwara 账号

  • 登录:/user/login → /user/token;Token 使用 AndroidX Security 加密存储,密码不落盘
  • 注册:登录框的“注册”在应用内打开官网注册页 www.iwara.tv/register(WebView),人机验证和邮箱确认由官网完成,注册成功即为官网账号;站内链接留在页面里,站外链接交给系统浏览器,也可一键改用浏览器打开
  • 点赞:POST / DELETE /video/{id}/like
  • 点赞列表:/favorites/videos,后台完整翻页同步并计入已看
  • 关注、好友关系同步

收藏与浏览历史

  • 爱心 = Iwara 官方点赞,同步到服务端;五角星 = 本机收藏,存在本地 SQLite。两者互不影响
  • 浏览历史记录最后播放位置、时长和是否基本看完
  • 独立 seen_videos 表永久记录推荐系统使用的“已看视频 ID”,数据库升级时自动迁移
  • 我的收藏、浏览历史、已下载共用同一套卡片列表布局

搜索与下载

  • 中英日韩四语互搜(只用于「视频名」和「标签」两栏,作者名只按输入的原词搜):输入其中任一种语言,自动补上另外三种写法一起搜,结果并成一份
    • 例:搜「克拉拉」会同时按 Clara、クラーラ、클라라 去搜;输入 Clara 同样会补上中日韩三种
    • 先按语言特征认出输入属于四种里的哪一种(认不出的按英文那一路处理,另外三种照样补齐)
    • 配了 AI 翻译就问 AI 一次要齐四种写法(专有名词有通行译名,比通用翻译准);没配就走谷歌免费接口,一个目标语言一个请求;哪一路失败就少一种写法,搜索照常进行
    • 译文回来之前先用原词搜着,回来后把新写法补进正在搜的三栏,已经拿到的结果不动
    • 几种写法轮流翻页(一次只发一个请求,请求量和单语言时一样),结果按 id 去重后并入同一份列表,再按当前排序统一排;全部写法都翻完了才算到底
    • 「作者名」一栏不做互译:作者的用户名是本人起的那一个,翻成别的语言反而搜偏
    • 太长的输入(超过 40 字,那是句子不是搜索词)和没有文字的输入不做互译;译好的写法按原词缓存,同一个词不会翻第二次
    • 状态栏写明这次实际在搜哪几个词
  • 独立的搜索结果页,三个标签页:
    • 视频名:/search?type=videos&query=...
    • 标签:/videos?tags=...;空格、逗号、顿号分隔的多个词表示同时带这些标签,无结果时按下划线、连写当作单个标签重试
    • 作者名:/search?type=users&query=...,显示头像和关注数并可进入作者主页
  • 排序:
    • 视频名、标签两栏默认上传时间 · 倒序(先看到最新的),另可切到播放量、点赞数,并能切换顺序 / 倒序
    • 排序键随请求一起发给服务端(列表接口的 sort=date|views|likes),换排序键会从第一页重新翻,排的是整批结果而不只是已加载的几十条
    • 顺序(升序)只在已加载的结果里换方向:Iwara 没有升序参数
    • /search 接口对 sort 的支持没有文档保证:它要是因此报错,自动退回不带排序参数再请求一次,结果只按本地排序显示
    • 缺少上传时间的结果不参与按时间排序,一律排在最后;数值相同的按 id 定序,翻页时不会来回换位置
    • 作者名一栏没有排序入口,固定按关注数多的优先,服务端没回报关注数的排在后面
  • 视频结果保留不可播放作品并显示原因,可播放的在结果内竖滑播放
  • 下载走 Android DownloadManager,下载前可选清晰度
  • 已下载页面:App 记录下载过什么,页面向系统下载器查询实际状态
    • 已完成的直接播放本地文件;仍在下载 / 失败的在卡片上标出;系统里已查不到的退回在线播放
    • 同一视频的不同清晰度各算一条,重新下载同一清晰度覆盖旧记录
    • 打开页面时自动补录系统下载器中本应用发起过、但本地表没有的下载(按文件名 <标题>_<视频 id>_<清晰度>.mp4 从右往左解析)

应用内更新

  • 启动后后台检查 GitHub 最新 Release,约 6 小时一次;主菜单可手动检查
  • 先走 GitHub API(/repos/…/releases/latest,带更新说明);API 连不上或被限流(未登录每小时 60 次,共用出口 IP 时容易碰到)时退到发布页 github.com/…/releases/latest 的 302 跳转地址,从 /releases/tag/vX.Y.Z 取版本号,APK 地址按固定文件名拼出
  • 检查结果、失败原因、更新包下载开始 / 失败(含 DownloadManager 原因码)都写入诊断信息;连接层错误提示为“连不上 GitHub,请检查代理 / VPN”
  • 显示当前版本、新版本号和更新内容;下载固定签名的 IwaraFlow-signed.apk 后拉起系统安装
  • Android 8+ 未授权“安装未知应用”时自动进入授权页,返回后继续安装

菜单与设置

主菜单:登录(含注册入口)/ 退出、浏览历史、我的收藏、已下载、已关注用户、设置、检查更新、重新加载当前流。

设置页:

分组 内容
推荐 刷新推荐时排除已看视频;「最新 / 流行 / 人气」也排除已看(默认关);显示推荐调试信息(默认关);老片穿插间隔(关闭 / 8 / 12 / 16 / 24)
播放 播放完毕自动进入下一条;切到后台自动进入画中画;暂停时显示播放三角;点一下画面暂停播放(默认开);前进 / 后退秒数
默认清晰度 对之后播放的视频生效;当前视频用右侧画质按钮切换
网络 手动代理(HTTP / SOCKS,主机 + 端口),进程级生效,播放器、图片和接口请求全部经过
翻译 翻译服务:谷歌免费接口(默认,无需密钥)/ DeepL / 微软 Azure / 百度翻译开放平台 / LibreTranslate / AI 翻译(选服务商:内置九家只填 API Key,自定义填地址 + Key + 模型名)/ 自定义接口,各自填密钥或地址
维护 同步点赞记录;兴趣管理(列出点过「不感兴趣」的作者 / 标签,点一项即可恢复);诊断信息(含推荐质量指标)
  • 维护项是动作而非开关,点击立即执行,不需要保存,也不关闭设置页
  • 保存设置只在候选真正受影响(排除已看、老片穿插改动且当前在推荐流;榜单排除已看改动且当前在榜单流)或代理改动时重新加载列表,其余设置直接应用到当前卡片,不打断播放
  • 诊断信息写成 txt 文件(保留最近 5 份),可复制或直接以文件形式分享到其它应用;只记录异常、退出原因和加载线索,不记录账号或视频列表,不自动上传

推荐算法

推荐页不直接照搬某一个官方榜单,而是从站内存档抽样、本地打分排序后再按位置插入关注更新和老片。

站内规模

按发布时间翻到底 第 10147 页(网页端一页 32 条)
全站视频总数 约 32.5 万
换算成 App 的 36 条一页 约 9000 页
最早的投稿 2014 年 3 月
近期新增速度 每月约 6000 条 ≈ 167 页

一千多页只覆盖最近半年,抽页上限两千两百页刚好对上“一年以内”这条线;早年的更新速度远低于现在,越靠后的页一页覆盖的时间越长。

候选来源:在整个存档里抽页

每一轮刷新都在各来源的存档里随机抽页:

来源 抽页范围 说明
关注作者的更新(/videos?subscribed=true&sort=date) 第 0 页 + 最多 200 页 首页保证新,往后是没看过的存量更新
最新投稿(sort=date) 第 0 页 + 最多 2200 页(约一年) 和“经典”的分界线对齐(> 1 年才进老片池),一年以内的存量都能抽到;上限还受服务端回报的总页数约束
流行(sort=popularity) 第 0 页 + 最多 60 页 越靠后越老、越没人看,不再往深取
热门(sort=trending) 第 0 页 + 最多 6 页 轮换快
本月 / 上月点赞榜(sort=likes&date=yyyy-MM) 前 3 页随机 近期里真正受欢迎的作品;按时间随机抽到的近期视频大多点赞很少,这一路把“赞多的”补进来。若服务端回报的总数是全站量(说明过滤没生效),本次结果丢弃并停用
个性化召回 标签 tags= 前 2 页随机、作者 user= 第 0 页 画像里权重最高的 2 个标签(≥ 1.5)和 1 位作者(≥ 2.5,按作者 id)
  • 抽页概率偏向靠前(页码按均匀随机数的立方缩放):新内容优先,尾巴足够长
  • 第 0 轮固定包含各榜单首页,冷启动不受影响;没看过的候选不够时继续抽新页,而不是往后挪一页
  • 两次刷新不会落在同一批页上
  • 总页数来自接口回传的 count:每轮第 0 页请求都会带回总条数,抽页范围随之更新;表中的数字是策略上限,实际取两者中较小者
  • 退路:服务端不回报 count 时,某页请求成功却为空即把该榜单上限压到该页以下;超时和失败不算数,并有下限保护

关注的作者按位置插入

关注作者的更新不参与打分加权,而是每 5 条未关注内容配 1 条关注作者的更新(占比 1/6),插在这一组内的随机位置。关注更新不足以铺满时自动拉大间隔,均匀散布在最终显示的那一段里;一条都没有时列表原样返回。

关注名单每 6 小时在后台更新一次,另外:

  • 同步成功但一个都没有(全部取关了)会把名单清空;只有同步失败才保留旧名单。以前只在“拿到非空名单”时才写回缓存,于是取关之后那些作者仍被当成已关注
  • 在作者页或视频流里点了关注 / 取关,会立刻通知推荐引擎改名单,不用等缓存过期

近期优先,老片按间隔穿插

年龄分三桶,不是一刀切(以前半年是硬边界,179 天和 181 天待遇天差地别):

桶 年龄 待遇
近期 ≤ 90 天 推荐流主体,新鲜度分最高
中期 90 天 ~ 1 年 仍在推荐流主体里,新鲜度按连续曲线自然衰减
经典 > 1 年 进老片池,按间隔穿插

接口没给发布时间的算近期。近期 + 中期不足 24 条时才用经典补足,不给空页。

老片池 = 专门抓的老片 + 候选里分流出来的老视频。专门抓的老片来自 sort=likes 第 8 页以后随机抽的一页,只取发布超过一年、未点赞、未收藏的(开启排除已看时也排除已看)。

老片池同样个性化:按“质量分 + 画像 ×0.5”排序(不算新鲜度——老片本来就老,再按年龄罚一次没有意义),再做一次内容打散。穿插进来的是“历史上质量高、而且比较符合你口味的作品”,不是“全站经典”。在主体之上,每 12 条一组,组内随机位置塞 1 条老片;老片请求失败或超时不影响首屏。间隔可在设置中调整;关闭穿插后老视频不再出现在推荐流里。

打分

  • 来源分按分组算,不是每命中一路就往上加:热门 / 流行 / 月高赞 / 老片同属「站方热度」,个性化召回(标签 / 作者)是「个人口味」,订阅流是「社交」,最新投稿是「新鲜」。同一组里取最高分,多命中一路只加 0.2;跨组才按 ×0.55 叠加。以前同时上三个榜的作品会被 +0.55× 两次,而点赞和播放量又已经算进质量分,等于把“热门”这一件事奖励了三四遍
  • 来源权重会自己学:从曝光数据算每一路召回的「1 − 划走率」,相对全局平均取比值,样本少时往 1.0 收缩(三五条不足以把一路抬上天),限幅 0.6~1.6,乘在下表那些写死的权重上。某个人标签召回长看率 72%、热门榜只有 21%,下一轮就会多给标签召回一点比重;总样本不到 40 条不学。诊断信息里能看到当前学到的系数
  • 来源权重与该来源里的排名
  • 站方质量分:平滑点赞率为主、热度为辅。点赞率按贝叶斯平滑(先验 400 次播放、5% 点赞率),相对平均水平取对数(限幅 −1.5~2.5)×1.6,再加 0.5·ln(赞+1) + 0.12·ln(播放+1);十次播放五个赞压不过十万播放一万赞,同等热度下点赞率高的靠前,纯点赞数的老片优势被削弱
  • 视频新鲜度(衰减曲线较缓,存档深处的视频仍有机会)
  • 本地画像(可正可负,限幅 −6~8 后 ×0.38):作者按名字和 id 两套键、标签按名字累计权重、视频按 id 单独一维(「不感兴趣:当前视频」只落在这一维)
  • 少量稳定扰动,避免结果僵化
  • 不按页码衰减:深页不比首页差,只是更老,由新鲜度评判

行为信号与画像

行为 权重 条件
点赞 +2.0
收藏 +1.4
下载 +1.1
观看 连续值(见下) 离开这条视频时记一笔,正的记 watch、负的记 skip(负反馈只在翻页划走时记,切后台、进内部页面不算)
官方历史点赞(种子) +1.2 同步官方点赞时把最近 500 条种进画像,每条只记一次
发评论 +1.5 发送成功时记
分享 +1.0 点分享按钮时记
打开评论区 +0.3
点进作者主页 +0.3 从视频卡片点作者名
关注 / 取关作者 +1.5 / −1.0 作者页操作成功时记,只记作者不记标签
搜索 +0.25,3 小时半衰 只当短期意图:关键词按空格 / 逗号拆成标签记入(最多 6 个)。一次好奇的搜索不该把长期画像带偏
从搜索结果点开 +1.0 真正点开才是兴趣,比单纯搜索重
不感兴趣 视频 −6.0(只压这一条)/ 作者、标签 硬屏蔽 长按画面上半区弹出面板,按类型选:当前视频、作者、某个标签(最多列 8 个);三档各管各的维度——「当前视频」只写视频 id,不碰作者也不碰它的标签;「作者」只写作者;「标签」只写那一个标签。作者 / 标签那两档写进独立的 muted_entities 表,不进入打分,直接从候选里剔除(见下)。同时标记已看;推荐流里直接跳到下一条
取消点赞 −1.2
取消收藏 −0.9
连续跳过同类内容 额外 −0.5 连着快速划走两条同作者或有共同标签的视频,只对共同的那一维再记一笔;看得久会打断连击
长期持续快速划走 作者额外 −1.5 / 标签额外 −0.8 同一作者 / 标签在画像窗口(最近 2000 条行为)里攒够 5 次快速划走

观看兴趣值(连续,不再是固定档位):

兴趣 = ln(1 + 播放秒数 / 12) × 0.38 + 播放比例 × 0.9 − 基线(10 秒)
       + 播完 0.35 + 重看 0.3 + 往回拖过 0.15 + 看的过程中点赞收藏 0.25
       − 起播就走的惩罚(刚起播 0.45,到 4 秒线性归零)
  • 43 秒和 45 秒不再一个没信号、一个 +0.8;播完也不再反而比看满 45 秒低(播完约 +2.3)

  • 绝对值不到 0.08 当作没有态度,不记进画像

  • 看了 10 秒左右是“不好不坏”的分界;起播就划走约 −0.68

  • 标签权重按作者权重的 0.45 累计;一条视频最多按命中最强的 4 个标签计分(按绝对值取,强负反馈的标签同样算得进来),标签多的视频不再天然占优

  • 长期口味存在单独的聚合表(preference_entities):每发生一次行为就“旧分按时间衰减 + 这次的增量”写回去,一个月折半。以前画像只读最近 2000 条行为,重度用户做完两千次别的操作之后,常年喜欢的那个作者不是慢慢淡掉,而是整个滚出查询窗口、一夜之间从画像里消失

  • 最终画像 = 长期聚合 + 当前会话:最近 45 分钟的行为再补一份加成(总量仍是 ×2.5),连着看几条同一主题,后面的推荐马上跟上。搜索的短期意图、官方点赞种子、视频级的「不感兴趣」不进聚合表,只留在行为窗口里按各自的规则算

  • 行为表保留最近 3000 条(摊销修剪:攒够 100 条才检查一次,超出上限 200 条才真的删;以前每插一条就跑一次要排序三千行的 DELETE),算画像读最近 2000 条

  • UI 线程不写库:划走、点赞、收藏这些写操作排到一条专用写线程上,不和后台算画像抢同一把锁

  • 账号作用域:官方点赞种子和同步进来的已看标记带账号 id;关注名单也按账号更新。本机兴趣默认共享,可在「设置 → 数据与存储」开启按账号隔离;开启后每个账号及未登录状态分别保存系统 / 手动兴趣及屏蔽,原共享兴趣保留,收藏和历史仍共用。

  • 播放失败后划走不计负反馈,网络问题不污染画像

  • 隐式负反馈只降权,不永久屏蔽:划得快、取消点赞这些是“猜”出来的不喜欢,画像分进打分时限幅在 −6~8(×0.38),不会把候选直接剔除;画像分低于 −1 的“明显不喜欢”内容打分后沉在底部,正常露不出来,但每 30 条正常推荐配 1 条从中挑出的探索位(随机位置),口味变了还有机会被重新发现;其余继续留在底部

  • 显式负反馈压过所有隐式正反馈:点过「不感兴趣:作者 / 标签」的内容走硬过滤,在打分之前就从候选里剔除——顺序是 候选 → 硬过滤 → 打分 → 多样性 → 探索。以前它只是一个很负的权重,要和“看得久”“点过赞”一起加权算,一个又拉黑过、又恰好命中几个喜欢标签的作者照样能排上来。个性化召回也直接排除这些作者 / 标签,不再抓回来又被滤掉

  • 拉黑不会自己过期:它记在独立的 muted_entities 表里,不在滚动的行为窗口里(行为表只留最近 3000 条、画像只读最近 2000 条),刷得再多也不会被挤掉。唯一的解除方式是设置 → 维护 → 兴趣管理里的“恢复”,探索位也不给

多样性

两层:

  1. 作者打散:同一作者在任意连续 5 条里最多出现一次,打分高的作者的其余作品往后挪,各自内部顺序不变
  2. 内容打散(轻量 MMR):打散作者解决不了“二十条不同作者、全是同一种内容”。每选一条时,在最前面的 16 条候选里挑和最近 3 条最不像的——代价 = 名次 × 0.06 + 相似度 × 1.2。相似度不用任何模型:同一个作者算 1.0,否则看标签的 Jaccard。没有相似内容时结果和原顺序完全一致

候选建模

候选从召回到展示一路带着自己的来源信息(RecommendationCandidate):来源权重与榜单位置、命中的画像标签 / 作者、站方质量分,以及「是关注的作者 / 老片 / 探索位」这几个标记。

  • 实时重排因此和第一次排序是同一套口径:来源分从候选表里取回来,只有口味那一项跟着新画像变。以前队列里只剩 VideoItem,用户点一次赞整条队列就换了一套评分体系
  • 顺带能回答「为什么推荐给我」:关注的作者更新了 / 为你探索的新内容 / 你最近常看 #标签 / 你喜欢这位作者 / 历史高赞 / 近期高赞 / 热门榜 / 流行榜 / 最新投稿 / 猜你喜欢
  • 「猜你喜欢」在最终推荐列表中按正向行为证据分配,每批最多占四分之一,批内两条「猜你喜欢」之间至少隔开三条;关注、探索、老片、标签及作者召回的明确理由优先保留,每种已有来源理由至少保留一条。该分配只影响理由展示,不改视频顺序或打分,实时重排、界面和曝光记录使用同一口径。
  • 候选表最多记 2000 条,按最近用到的顺序淘汰(有界 LRU),不再“到 2001 条整张清空”——清空会让屏幕上正在看的那几条突然说不出自己为什么被推荐
  • 候选带轮次号(每次完整刷新 +1):同一条视频在新一轮里被重新召回时不会沿用上一轮的来源分、命中标签和“探索位 / 老片”标记。上一轮它可能是“为你探索的新内容”,这一轮只是官方榜单回退来的

实时重排

推荐流一次生成 80 条候选,翻页时逐批从队列里取。点赞、收藏、分享、发评论、不感兴趣之后,每翻 4 页,以及从搜索页 / 作者页 / 关注列表回到主页时,按此刻的画像把队列里还没展示的候选重新排序(来源分 + 质量分 + 新鲜度 + 画像,再做作者打散);已经在流里的卡片不动,也不发网络请求。重排在后台线程算,回来时只替换仍在队列里的那部分。

候选耗尽时的降级

推荐队列见底就重新生成一批。只有连着 2 次都一条新内容都拿不到才退回官方榜单分页——以前是“固定生成 3 批就降级”,刷得久的用户必然被踢出个性化推荐。

退回之后官方候选也不是原样贴上来,同样要走本地这一套:排除已看 → 本地评分(来源 + 质量 + 新鲜度 + 画像)→ 作者打散。

推荐诊断与兴趣管理

单元测试回答的是「算法有没有按写的规则跑」,回答不了「这套规则有没有让推荐变好」。设置 → 维护 → 诊断信息里因此多了一段推荐指标,全部只算本机数据、不上传:

指标 用途
快速划走率 最直接看出推荐有没有跑偏
平均有效播放时长 比点赞数量密集得多的信号
播放完成率 内容匹配程度
点赞 / 收藏率 强正反馈
同作者重复率 作者多样性
同标签重复率 内容多样性

这些数按曝光算,而且分流(recommendation_impressions 表):每条视频进推荐流时记一行——在第几位、来自哪些召回、当时的分数和推荐理由、是不是探索位 / 老片——离开时补上真实播放毫秒数、有没有播完、是不是被划走、有没有点赞收藏。

这解决了两个以前算不准的地方:

  • 播放器是所有页面共用的,在作者页连看一小时同一个作者,那些观看以前也会被算进“推荐质量”。现在只统计推荐流自己的曝光
  • 平均播放时长以前读 history.last_position:直接拖到 8:00 看十秒,统计出来接近“看了八分钟”。现在读的是播放器实际播了多久

诊断里还会按来源拆开一行行列出来(标签召回 / 作者召回 / 月榜 / 热门 / 最新 / 探索位 / 老片各自的样本数、划走率、平均播放),于是可以回答“标签召回到底有没有用”“探索位成功率多少”,而不是只能看一个混在一起的总平均。表最多留 2000 条,只在本机,不上传;刚升级上来还没有曝光时退回老口径。

取最近 200 条,于是可以说「最近 100 条:快速跳过率从 42% 降到 27%,平均播放从 19s 升到 31s」,而不是凭感觉说「好像推荐不太准」。

设置 → 维护 → 兴趣管理列出点过「不感兴趣:作者 / 标签」的条目,点一项就恢复(同时删掉硬屏蔽记录和那条压分的负反馈):拉黑是永久的、连探索位都不给,这里是它唯一的出路——口味变了、或者点错了,不该永远出不来。

推荐调试信息(设置 → 推荐里的开关,默认关)打开后,简介面板会在推荐理由下面写清这条视频的分是怎么来的:

总分 9.47
来源 +2.80 · 质量 +3.16 · 新鲜度 +1.21
画像 +2.15 · 扰动 +0.15
命中标签:#MMD +2.10,#dance +0.60
作者画像 +1.70
来源:trending、month_top
年龄:近期
第 3 轮推荐

打分和调试信息读的是同一份拆解(ScoreParts),两边永远对不上不了。

简介面板里还会写明推荐理由(「你关注的作者更新了」「你最近常看 #标签」「为你探索的新内容」等),只有推荐流有,最新 / 流行 / 人气这些按榜单排的流不写。

排除已看

开启后,seen_videos 中的视频在下一次生成推荐列表时被过滤。候选按“没看过 / 看过但没点赞 / 已点赞收藏”分三档:没看过的不足 12 条时继续抽页,仍不够时补看过但没点赞的,已点赞收藏的只在没有别的可推时使用,不会给出空页面。

Iwara 官方点赞会完整同步进 seen_videos(服务端一页最多 50 条,后台按页读完),每 6 小时一次,也可在设置中手动触发。

「最新 / 流行 / 人气」也排除已看是它下面的一个独立开关,默认关:那三个页面是照着官方榜单看的,默认少掉几条会让人觉得“榜单不对”。打开之后它们和推荐流一个口径,刷过的不再重复出现;某一页全看过时仍然照原样给出,不给空页。

诊断信息中记录本次刷新抽到的页码和用到的个性化召回。

技术说明

技术栈

  • Kotlin,ViewPager2 竖滑流
  • AndroidX Media3 / ExoPlayer 1.11.0,CacheDataSource / SimpleCache 磁盘缓存
  • OkHttp、Coil
  • SQLiteOpenHelper 本地数据库;AndroidX Security Crypto 加密会话
  • Android ImageDecoder / AnimatedImageDrawable 播放内置 GIF 动画(minSdk 28,无第三方动画库);两段素材均为 560×560、70ms/帧(点赞 26 帧,收藏 35 帧),按屏幕显示尺寸解码
  • Android DownloadManager、Picture-in-Picture、FileProvider
  • GitHub Releases 应用内更新

推荐模块的分工

推荐拆成召回和排序两半,各管各的:

负责
RecommendationEngine 召回与编排:抽哪些页、发请求、翻页深度上限、按月榜 / 标签 / 作者的个性化召回、关注名单、候选分桶(已看 / 已赞)、老片抓取
RecommendationRanker 排序:打分(来源 + 质量 + 新鲜度 + 画像)、作者打散、内容 MMR 去重、探索位、老片个性化、关注按位置插入、最终装配;还持有候选表(来源信息、推荐理由)

| WatchInteractionTracker | 一张卡片「看得怎么样」:播放时长记账、READY / 播完 / 出错 / 往回拖,以及离开时折算成口味信号和曝光结果 | | SettingsDialogController | 设置弹窗那三百行:六段选项的界面、校验、存偏好,以及“保存之后要不要重拉列表” | | FeedSessionStore | 顶部四个流各自的现场(列表、看到第几条、翻到第几页),切回来时照原样恢复 |

RecommendationRanker 不发网络请求、不碰数据库,全是纯计算;改排序策略不会动到召回,反过来也一样。WatchInteractionTracker 不碰任何 View,只认播放器的几个事件。

VideoAdapter 目前仍负责播放器与手势,MainActivityV3 负责 Feed 编排、导航、下载与更新。

数据与隐私

敏感数据只进加密存储(SecureSessionStore / AndroidX Security Crypto):

内容 存在哪
Iwara 的 refresh / access token 加密存储
翻译 / AI 服务的 API Key、百度 APP ID、自定义 Authorization 头 加密存储(老版本存在普通 SharedPreferences 里,升级时自动搬过去并删掉明文)
画质、推荐参数、代理地址、翻译服务商和地址 普通 SharedPreferences
浏览记录、收藏、行为画像、长期口味、拉黑名单、推荐曝光、下载记录 本地 SQLite (iwaraflow.db),当前 v10
当前登录的 Iwara 账号 id(公开 id,非密钥) 普通 SharedPreferences;用来给云端导入的数据划账号作用域
  • Keystore 出错时不再退回明文:以前加密存储打不开会退到普通 SharedPreferences,把 refresh token 明文写在磁盘上。现在这种情况下密钥只放内存,进程结束就没了(重新登录即可),磁盘上一个字节都不留;老版本留下的明文文件在启动时删除
  • 登录密码从不落盘
  • 备份规则(data_extraction_rules.xml / backup_rules.xml):加密存储和浏览记录数据库既不进云备份也不跟着换机走;设置项照常备份。诊断信息写在 cacheDir 下,系统本来就不备份缓存目录
  • 诊断信息只记录异常、退出原因和加载线索,不含账号、密钥和视频列表,不自动上传

发布签名说明:仓库里的 signing/iwaraflow-dev.jks.b64 和 CI 里的口令是公开的,任何人都能用同一身份签出 APK。这是为了让任何人 fork 之后都能直接构建出可覆盖安装的包;它不是、也不应被当作正式发布用的私钥。若要把本项目当作正式分发渠道,必须换一把只存在于仓库 Secrets 里的签名密钥,并按 Android 的签名密钥轮换(signing lineage)机制过渡——直接删文件没有用,Git 历史里已经公开过。

播放与缓冲

  • 竖滑流缓冲上限 25 秒(ExoPlayer 默认 50 秒),起播缓冲 1.2 秒;画质由视频源决定,不受影响
  • 当前视频稳定 READY 后,在网络空闲阶段预缓存后续视频的前约 2 MB:Wi-Fi 预缓存两条,移动数据或下行低于 4 Mbps 只预缓存一条
  • 播放器与预缓存共用同一 CacheDataSource,约 256 MB LRU 上限;多个 Activity 共用同一个 SimpleCache
  • 播放器 decoder fallback

生命周期

  • onPause 只暂停不释放播放器(半透明界面盖上时页面仍可见);onStop 才释放解码器
  • 分享:目标应用以显式 Intent 通过 ActivityResult launcher 拉起(不经过系统选择器),期间标记为“正在打开内部页面”,不触发自动小窗,也不暂停播放;主界面 windowSoftInputMode="adjustNothing",评论输入层是独立 Dialog 窗口,键盘只顶起它
  • Activity 销毁时网络客户端在后台清理,不在主线程关闭 TLS 连接
  • 请求提交与关闭共用同一生命周期保护,丢弃已关闭页面的迟到结果
  • 各子页面使用 AndroidX 返回分发,系统按键与手势共用同一返回路径

评论面板几何

面板高度 = 屏幕高度 − 顶栏高度 − 画面按 fit 铺满宽度时的高度,限制在屏幕高度的 45%~70% 之间;画面区域顶边 = max(顶栏底边, 屏幕高度 − 面板高度 − 画面高度)。横屏视频画面比区域矮时顶边下移贴住面板;竖屏视频画面比区域高时从顶栏底边开始并按高度缩小。两种情况画面底边都与面板顶边重合。

网络

  • 手动代理通过 ProxySelector.setDefault 设为进程级默认,OkHttp、Media3 的 HTTP 数据源和 Coil 全部经过;本机地址不走代理
  • 连接层错误(Connection reset、超时、DNS 失败、TLS 握手失败)在视频流的错误提示和诊断中统一翻译为“连不上 Iwara,请检查代理 / VPN 是否对本应用生效”。这类错误表示 Iwara 在当前网络下不可直达,不是应用故障
  • 页面上的失败提示统一走 IwaraApi.explainError,给用户看的是原因不是错误码:
    • 服务端错误码(errors.serverError、errors.notFound、errors.tooManyRequests 等)各有对应说法,认不出的码也写成“Iwara 拒绝了这次请求(…)”
    • 服务端没给错误码、只剩状态码时按 HTTP 码解释(400 / 401 / 403 / 404 / 429 / 5xx)
    • 压根没连上时按异常类型和消息解释(DNS 失败、超时、TLS 握手、连接被重置 / 拒绝),并提示检查代理 / VPN
    • 本来就是中文的提示(如“请先登录 Iwara”)原样显示

界面

  • 播放主界面深色沉浸式;登录 / 搜索 / 设置弹窗浅蓝白色主题,主按钮带 OEM 主题兼容兜底
  • 浏览历史、作者主页、搜索结果使用浅蓝卡片列表
  • 点赞 / 收藏使用圆润的爱心与五角星矢量图标,同尺寸;画质 / 下载 / 小窗按钮带文字说明
  • 专属 launcher 图标:黄色底、蓝色渐变的圆角播放三角与波浪,自适应图标(前景位图在 mipmap-*/ic_launcher_foreground.png,原图在 art/launcher-source.png);另带 Android 13+ 的 monochrome 主题图标(drawable/ic_launcher_monochrome.xml),跟随壁纸取色
  • 颜色令牌集中在 values/colors.xml(页面底色、顶栏、主文字、次文字、强调色、分隔线)。新写的布局引用令牌,不再散着写十六进制;老布局逐步替换

构建与发布

要求:JDK 17+、Android SDK 36、Gradle 8.13。

仓库里不放 gradle-wrapper.jar(二进制),所以一键脚本按「有 gradlew 用 gradlew → 系统装了 gradle 用 gradle → 都没有就按 gradle/wrapper/gradle-wrapper.properties 里的版本下载一份到 ~/.gradle/iwaraflow-dist」的顺序找 Gradle:

build-apk.bat               :: 默认 assembleDebug
build-apk.bat assembleRelease
./build-apk.sh              # Linux / macOS,同样支持传任务名

用 Android Studio 打开本项目直接构建当然也可以。

单元测试:gradle :app:testDebugUnitTest。设备测试(仅测试模拟器):gradle :app:connectedDebugAndroidTest,参数 -Pandroid.testInstrumentationRunnerArguments.backMode=key 或 gesture 分别验证系统按键与手势返回;测试使用合成数据,不需要真实账号。

每次推送到 main 后 GitHub Actions 自动:

  1. 配置 JDK / Android SDK / Gradle,运行单元测试
  2. 构建 release APK,使用仓库内固定 keystore 签名并用 apksigner verify 验证
  3. 上传 IwaraFlow-signed-APK Actions Artifact
  4. 按 versionName 创建对应的 GitHub Release,并上传 IwaraFlow-signed.apk 供应用内更新下载

已发布的版本不可变:如果 v<versionName> 这个 Release 已经存在,发布这一步直接失败。同一个版本号下换掉 APK,不同时间下载的人会装到不同的包,而应用内更新只比 versionName,谁都不会察觉。

因此每次推送到 main 都必须同时提高 versionCode 与 versionName。

更新日志

v0.13.11

  • README 与代码注释里去掉开发过程叙述(内部文档的条目编号、"可以单独测"之类),只保留功能说明、实现方法和更新日志

v0.13.10

  • 给拆出来的 WatchInteractionTracker 和 FeedSessionStore 补上各自的用例

v0.13.9

  • 设置弹窗(六段选项的界面、校验、存偏好)拆成 SettingsDialogController;顶部四个流各自的现场(列表、看到第几条、翻到第几页)拆成 FeedSessionStore

v0.13.8

  • 观看行为记账拆成 WatchInteractionTracker:播了多久、有没有播完、有没有往回拖、报没报错,以及离开时怎么折算成画像信号和曝光结果,从 VideoAdapter 里独立出来,不碰任何 View
  • 来源分不再重复奖励热门:热门 / 流行 / 月高赞归进同一个「站方热度」分组,同组取最高分、多命中只加一点点;跨组(个人口味 / 社交 / 新鲜)才照旧叠加。以前同时上三个榜的作品会被加两次 ×0.55,而点赞播放量又已经算进质量分
  • 来源权重会自己学:从曝光数据算每一路召回的长看率,相对平均值给 0.6~1.6 的系数乘在写死的权重上,样本少时收缩回 1.0。哪一路召回这个用户实际更吃得下,下一轮就多给一点比重
  • 推荐调试信息:设置里打开后,简介面板在推荐理由下面写清总分是怎么拆的(来源 / 质量 / 新鲜度 / 画像 / 扰动)、命中了哪些标签、来自哪一路召回、第几轮推荐
  • 长期口味不再突然失忆:新增 preference_entities 聚合表,每次行为按“旧分衰减 + 新增量”累加,一个月折半。以前画像只看最近 2000 条行为,重度用户刷够两千次之后老兴趣会整个滚出窗口、一夜之间消失;现在它只会慢慢淡掉。最终画像 = 长期聚合 + 最近 45 分钟的当前兴趣,总权重和以前一致
  • 推荐诊断改成按曝光统计:新增 recommendation_impressions 表,每条视频进推荐流时记下位置、来源、分数、推荐理由,离开时补上真实播放时长和结果。指标因此只看推荐流(以前在作者页看一小时也会算进“推荐质量”),平均播放也不再是 history.last_position(拖到 8:00 看十秒会显示“看了八分钟”);诊断里还能按来源拆开看每一路召回的表现。只存本机,不上传

v0.13.7

  • 「最新 / 流行 / 人气」也能排除已看:设置 → 推荐里新增的独立开关,默认关(那三个页面是照着官方榜单看的,默认少内容会让人觉得“榜单不对”)。打开之后它们和推荐流一个口径,刷过的不再重复出现;某一页全看过时仍照原样给出,不给空页
  • 关掉软件不会被判成“不感兴趣”:负反馈只在「页面还在前台、用户真的划到了下一条」时记。关应用、切后台、进小窗、换榜单重新加载、恢复上次会话都只记正面信号
  • 换账号不再串画像:从云端导进来的东西(官方点赞种子、同步进来的已看标记、关注名单)挂到账号上,本机自己的行为(看了多久、本地收藏、不感兴趣)仍然是设备级的。以前登录 A 同步完再登录 B,A 的点赞还在给 B 算口味、A 点过的视频对 B 也算“已看”,关注名单更是 6 小时内都还是 A 的;退出登录时这些一起放下(数据库升到 v8,来路不明的旧点赞种子清掉,下次同步在正确账号下重种)
  • 作者主页点进去就有内容:作品元数据一回来就显示列表,可播放验证挪到后台跑,跑完再更新卡片上的标记。以前要等整页 36 条全部“解析源 + 探测”完才进列表,弱网上要干等好几秒;还没验到的作品照常能点开,只有验出确定播不了的才拦住并说明原因
  • 登录后先种画像再出第一屏:登录成功时先同步第一页(最多 50 个)官方点赞种进画像,再生成第一批推荐(最多等 4 秒),剩下的点赞照旧后台补。一个用了多年的账号第一屏就该像认识你,而不是等第二次刷新
  • 推荐补量不再反复抽到同一批坏视频:这一轮处理过的候选(显示过的、还排着的、验证没通过的)都不再进队列;“连续几次拿不到新内容就回退官方榜单”的判据也改成有没有产出能播的结果,而不是“有没有没见过的候选 id”
  • 已发布的版本不可覆盖:CI 发现 Release tag 已存在就直接失败,提示先提高版本号,不再 --clobber 换掉同版本号的 APK
  • UI 线程不再写数据库:划一条视频要写好几笔(观看记录、行为、已看标记),这些方法都带锁,会和后台算画像抢同一把锁。现在写操作排到一条专用线程上,顺序照旧;行为表的修剪也改成摊销着做,不再每插一条就跑一次要排序三千行的 DELETE
  • 候选表改成有界 LRU 并带轮次号:不再“到 2001 条整张清空”(清空会让屏幕上的视频突然说不出推荐理由);同一条视频在新一轮被召回时也不再沿用上一轮的来源分和“探索位 / 老片”标记
  • 拉黑变成真正的硬屏蔽:点过「不感兴趣:作者 / 标签」的内容在打分之前就从候选里剔除(候选 → 硬过滤 → 打分 → 多样性 → 探索),个性化召回也不再去抓它们。以前它只是一个很负的权重,一个又拉黑过、又命中几个喜欢标签的作者照样能排上来
  • 拉黑不再会自己过期:搬进独立的 muted_entities 表(数据库升到 v7,旧记录自动迁移),不在只留最近 3000 条的行为窗口里,刷得再多也挤不掉;唯一的解除方式仍是兴趣管理里的“恢复”,它会同时删掉硬屏蔽和那条压分记录
  • 可播放验证的失败分两种:私密 / 已删除 / 无权限 / 仍在处理记 1 小时,连不上、超时、连接被重置只记 30 秒。以前弱网上闪断一次,那条视频接下来一小时都被当成坏的
  • 验证结果改成进程级缓存:主页验过的视频,切到搜索页、作者页不再重验一遍(上限 500 条 LRU)
  • 最新投稿抽页上限 1100 → 2200 页,和“超过一年才算经典”这条线对齐,一年以内的存量都能抽到
  • 作者打散优先按作者 id 认人:同名的两个作者不再被当成一个人,改了名字的也不再被当成两个人

v0.13.5

  • 推荐拆成召回和排序两半:RecommendationEngine 只管召回与编排,新的 RecommendationRanker 管打分、多样性、探索位、老片穿插和装配;排序那半不发请求、不碰数据库
  • 补上 Android 13+ 的 monochrome 主题图标,跟随壁纸取色
  • 一键构建脚本真的能一键了:build-apk.bat / build-apk.sh 按「有 gradlew 用 gradlew → 有 gradle 用 gradle → 都没有就按 wrapper 里写的版本下载一份」的顺序找 Gradle,不再直接让你去开 Android Studio
  • 颜色令牌集中到 values/colors.xml,新布局引用令牌

v0.13.4

  • 诊断信息里新增推荐指标:快速划走率、平均有效播放、播放完成率、点赞收藏率、同作者 / 同标签重复率,取最近 200 条本机记录,不上传
  • 兴趣管理:设置 → 维护里列出点过「不感兴趣」的作者和标签,点一项即可恢复
  • 简介面板显示推荐理由:「你关注的作者更新了」「你最近常看 #标签」「为你探索的新内容」等,只在推荐流显示
  • 可播放验证记录通过率,供诊断查看

v0.13.3

  • 消除 SQLite 的 N+1 查询:推荐候选分桶、老片筛选、首页和搜索页装点原来是每条视频各查一次「看过没」「收藏没」,几百条候选就是上千次查询;改成 loadStatuses(ids) 一次问清一批(按 400 个 id 分批)
  • 可播放验证加短期缓存:按「视频 id + 清晰度」记住验证结果,可播的记 10 分钟、明确不可播的(私密 / 已删除 / 无权限)记 1 小时,滑动时不再反复解析 CDN 和发 Range 探测
  • 收敛并发:接口客户端同时在飞的请求上限 16、同一主机 8;可播放验证同一 CDN 主机最多 6 个,后台探测不再和正在播的视频抢带宽

v0.13.2

  • Keystore 出错时不再把 token 明文写到磁盘:加密存储打不开时密钥只放内存,进程结束即失效;老版本留下的明文文件启动时删除
  • 翻译 / AI 的 API Key、百度 APP ID、自定义 Authorization 头改存加密存储,升级时自动从普通 SharedPreferences 搬过去并清掉明文
  • 明确了备份范围:加密存储和浏览记录数据库不进云备份、也不跟着换机走(dataExtractionRules / fullBackupContent),设置项照常备份
  • 读取翻译配置改到后台线程,启动路径不碰 Keystore
  • 修 CI:GitHub runner 的新 cmdline-tools 里没有 tools 包,setup-android 改成只装 platform-tools

v0.13.1

  • 搜索不再轻易带偏画像:搜索关键词从 +1.2 降到 +0.25,而且按 3 小时半衰(只算“这会儿想看看”);真正点开搜索结果从 +0.6 提到 +1.0
  • 观看反馈从固定档位改成连续值:按播放时长(对数)、播放比例、是否播完 / 重看 / 往回拖过 / 点赞收藏合成;43 秒和 45 秒不再一个没信号一个满分,播完也不再比看满 45 秒低
  • 标签不再直接求和:一条视频最多按命中最强的 4 个标签计分,标签多的视频不再天然占优;强负反馈的标签同样算得进来
  • 内容多样性(轻量 MMR):除了打散作者,还会按标签 Jaccard 相似度避免“二十条不同作者、全是同一种内容”
  • 探索位改探索“未知”:明确点过「不感兴趣:作者 / 标签」的内容不再占用探索位,只有隐式负反馈(划得快)才有机会再试
  • 老片个性化:老片池按“质量 × 口味”排序再穿插,不再是全站经典
  • 年龄软分桶:近期(90 天)/ 中期(1 年)/ 经典,中期仍留在推荐流主体里,取消半年硬切线

v0.13.0

  • 「不感兴趣:当前视频」不再污染作者和标签画像:画像新增视频维度,这一档只压这条视频(−6.0),作者和它的全部标签都不受影响;三个按钮各管各的维度
  • 刷久了不再退化成普通 Trending:固定“生成 3 批就降级”改成“连着 2 次拿不到新候选才降级”;退回官方榜单后同样走排除已看 → 本地评分 → 作者打散,不再原样贴一页热门
  • 候选带着来源信息走完全程(RecommendationCandidate):来源分、命中的标签 / 作者、质量分、关注 / 老片 / 探索位标记都保留,实时重排和第一次排序回到同一套口径;顺带能回答「为什么推荐给我」
  • 修复关注名单的空列表 bug:全部取关后旧名单不再被当成“已关注”;关注 / 取关立刻通知推荐引擎
  • 从搜索页 / 作者页 / 关注列表回到主页时重排一次候选:跨页面学到的兴趣当场生效

v0.12.6

  • 设置里新增「点一下画面暂停播放」开关(默认开)。关掉后点一下画面不再暂停,只在「标题 / 标签 / 操作栏」和「进度条 / 快进后退 / 剩余时长 / 小窗」之间切换,视频照常播
  • 点出来的控制行里按钮变成暂停图标,点它才暂停;视频暂停着时仍是播放三角

v0.12.5

  • 四语互搜只用于「视频名」和「标签」两栏;「作者名」改回只按输入的原词搜

v0.12.4

  • 搜索支持中英日韩四语互搜:搜「克拉拉」会同时匹配 Clara / クラーラ / 클라라 的结果,输入其他三种语言也一样补齐另外三种
  • 视频名、标签两栏按四种写法搜,轮流翻页、按 id 去重后并成一份结果,再按当前排序统一排
  • 配了 AI 翻译就问 AI 要四种写法(专有名词更准),没配就走谷歌免费接口;翻不出来时按原词照常搜
  • 状态栏写明这次实际在搜哪几个词

v0.12.3

  • 加载失败不再显示 errors.serverError 这类错误码,改成显示具体原因:服务端错误码、只剩状态码的 HTTP 失败、连不上网的各类异常各有说法,认不出的错误码也带一句解释
  • 搜索页、作者页、关注列表、评论区的失败提示都走同一套说法;搜索页已有结果时后续加载失败也会写明原因

v0.12.2

  • 搜索结果页新增排序入口:视频名、标签两栏默认按上传时间倒序(先展示最新的),可切换播放量 / 点赞数,并支持顺序 / 倒序
  • 排序键随请求发给服务端,换排序键时整批结果从第一页重新翻页;缺上传时间的结果排在最后
  • 搜索作者名改为按关注数多的优先,作者卡片上一并显示关注数

v0.12.1

  • 修复竖屏视频退出全屏后停在“只有进度条、没有信息栏”的样子:退出全屏会接着播,信息栏和操作栏随之回来
  • 左右滑动调进度的时间牌改成圆润胶囊背景;全屏时往下移(离底边 56dp,普通模式仍是 150dp 以让开信息栏)

v0.12.0

  • 简介 / 评论两页改成并排跟手滑动:拖动时跟着手指走,松手顺滑滑到目标页,点页签也是滑过去,不再直接跳
  • 简介页的标签可以点,点了直接搜这个标签(落在搜索页的「标签」栏)
  • 操作栏的小窗按钮换成全屏:全屏收起所有控件让画面铺满,横屏视频转到横屏、竖屏视频只收控件;全屏中暂停会显示进度条、快进 / 后退、剩余时长、小窗和退出全屏;返回键先退出全屏。小窗按钮移到暂停时进度条右上方,自动小窗设置不变
  • 新增按住画面左右滑动调进度:小幅是几秒的微调,划得越远跨度越大,画面跟着手指走,屏幕下方显示当前位置 / 总时长和偏移;全屏时同样可用

v0.11.6

  • 翻译来源不再显示“翻译自外语”:AI 翻译让模型在第一行报源语言代码;服务没报的按文字本身猜(假名 → 日语、谚文 → 韩语、西里尔 → 俄语、泰文 / 阿拉伯文,拉丁字母按常见功能词区分西 / 葡 / 法 / 德 / 意 / 印尼,越南语声调字母,否则英语);实在不知道只写“已翻译”
  • 暂停时的剩余时长放大(15sp 加粗)
  • “不感兴趣”面板顶部的灰条支持按住下拖收起,手势和评论面板一致

v0.11.5

  • 检查更新:GitHub API 连不上或被限流时退到发布页跳转地址取版本号,APK 地址按固定文件名拼出;检查结果和失败原因写入诊断信息;连接层错误提示改为“连不上 GitHub,请检查代理 / VPN”;更新包下载失败时给出原因码

v0.11.4

  • 探索位间隔从每 15 条改为每 30 条正常推荐配 1 条

v0.11.3

  • 负反馈画像补全:取消点赞 −1.2、取消收藏 −0.9;连续快速划走两条同作者 / 有共同标签的视频,对共同的那一维额外 −0.5;同一作者 / 标签攒够 5 次快速划走再额外压一层(作者 −1.5、标签 −0.8)
  • 负反馈只降权不屏蔽:画像分低于 −1 的内容每 30 条正常推荐配 1 条探索位(随机位置),其余沉在底部

v0.11.2

  • “不感兴趣”改为长按画面上半区弹出面板,按类型选择:当前视频、作者、某个标签,只写选中的那一维;下半区长按仍是 2× 加速。简介页里的按钮撤掉

v0.11.1

  • 推荐实时重排:点赞、收藏、分享、发评论、不感兴趣之后,以及每翻 4 页,按最新画像重排还没展示的候选,不发网络请求
  • 行为学习补全:发评论、分享、打开评论区、点进作者主页、关注 / 取关、搜索关键词、从搜索结果点开都计入画像
  • 新增“不感兴趣”:作者和标签记负反馈、标记已看,推荐流里直接跳到下一条

v0.11.0

  • 推荐:站方质量分改为平滑点赞率 + 热度;新增本月 / 上月点赞榜、热门榜再抽一页作为候选,把近期里赞多的作品补进来(此前近期候选几乎全来自按时间随机抽页,点赞普遍很少,而高赞的热门首页大多已看过被过滤掉)
  • 推荐:行为信号补全——看得久 / 看过一半记正面,起播后很快划走记负面(播放失败不算),画像可正可负;最近 45 分钟的行为按当前兴趣加倍;官方历史点赞的最近 500 条种进画像作冷启动;按画像里权重最高的标签和作者做个性化召回;同一作者在连续 5 条里最多一次
  • 收藏 / 已下载 / 浏览历史改为列表 + 竖滑播放流:从点中的那条开始,上滑下一条,到底提示“没有更多视频了”;已下载的直接放本地文件
  • 作者作品播放流不再首尾循环,最后一条再往上拉或播完时提示“没有更多视频了”
  • 暂停时进度条右上方显示剩余时长,拖动进度条时屏幕下方显示“当前位置 / 总时长”
  • 修复长按加速一会儿就失效:加速中允许手指挪动约 48dp,并禁止翻页控件截走手指
  • 点标签行也能打开简介;简介 / 评论面板内容区支持左右滑动切换页签
  • AI 翻译内置九家服务商预设(OpenAI、DeepSeek、通义千问、Kimi、智谱、硅基流动、Gemini、xAI、OpenRouter),只需填 API Key;选“自定义”才填地址和模型。请求不再带 temperature(推理类模型会拒绝),地址补全兼容 /v1beta/openai 这类路径,失败原因写入诊断信息

v0.10.1

  • 修复登录密码框和翻译 API Key 框明文显示:设为单行时输入框的变换方法被换掉,密码遮罩随之丢失,现在单行设置后重新装回圆点遮罩

v0.10.0

  • 推荐流改为近期优先:主体只放发布不满半年的视频,候选里抽到的老视频并入老片池,只按设置的间隔(默认每 12 条一条)穿插;关闭穿插后老视频不再出现。最新投稿抽页上限收到 1100 页(约半年)、流行榜 1000 页。修复此前存档深页的老视频凭点赞和播放量霸榜、连续多条都是几年前作品的问题
  • 登录框新增“注册”:在应用内打开官网注册页(WebView),人机验证和邮箱确认由官网完成,注册成功即为官网账号;可切换到系统浏览器打开
  • 翻译服务新增“AI 翻译”:任何兼容 OpenAI 聊天接口的服务(中转站、DeepSeek、通义、Kimi、硅基流动等),填接口地址、API Key、模型名即可;地址写到 /v1 自动补全,模型默认 gpt-4o-mini
  • 翻译接口出错时把服务端返回的原因(error.message)带进提示

v0.9.7

  • 修复关掉作者页 / 搜索页小窗后打开应用进入黑屏推荐页、各榜单和作者页都打不开:小窗被关掉时子页面的登记被撤销,主页找不到它,卡在“正在打开内部页面”状态。现在只有小窗被展开成全屏时才撤销登记,被关掉时保留,主页恢复时据此把它拉回前台

v0.9.6

  • 关闭作者页 / 搜索页的小窗后再打开应用,回到的是小窗里刚才那条视频,而不是推荐页:小窗被关掉时子页面只停止播放、不再结束,主页恢复时发现有子页面停在自己的任务里就把它拉回前台并接着播

v0.9.5

  • 修复作者页 / 搜索页进小窗后从桌面打开应用仍是小窗浮在黑屏主页上、菜单里的页面都打不开:展开小窗改为再启动一次小窗页面(和桌面图标展开主页小窗是同一机制),moveTaskToFront 对画中画任务只置顶不展开;若过一会儿主页仍在前台则关闭小窗并解开“正在打开内部页面”的锁,主页恢复播放
  • 修复关闭小窗后没画面但声音还在:退出画中画时页面已停在后台说明小窗被关掉,此时停止播放;作者页 / 搜索页同时结束自身,把结果交回主页
  • 不再申请 REORDER_TASKS 权限

v0.9.4

  • 修复评论 / 简介面板打开时遮住画面:底部留白此前被限制在卡片高度的一半,面板超过半屏时画面被居中推回面板底下。改为上下留白合计最多占卡片的 5/6,画面始终落在顶栏与面板之间
  • 修复作者页 / 搜索页进小窗后主页被顶到前台、推荐页黑屏、小窗浮在上面:小窗页面进小窗前先登记;主页恢复时若本应用另有页面在小窗中,被动露出的主页退回后台,从桌面图标打开的主页则把小窗所在任务拉到前台展开
  • 下载记录新增作者 id、用户名、简介(数据库 v5):已下载视频离线、或视频被作者设为私密后,仍能进作者主页和看简介;旧记录在联网拉到一次详情后自动回写
  • 已下载视频点作者名时若记录里没有作者信息,先拉一次详情再进作者页;服务端错误码(如 errors.privateVideo)翻成可读说明

v0.9.3

  • 修复已下载视频打开后黑屏、之后切到任何榜单都黑屏:本地播放在 onResume 里启动时没有恢复播放开关
  • 已下载视频播放时后台补拉一次详情,补上作者 id、简介、点赞数,评论区、简介页和进作者主页都能用
  • 作者页 / 搜索页的小窗被系统挪到独立任务后,从桌面打开应用会把那个小窗展开到前台,不再出现小窗浮在黑屏推荐页上

v0.9.2

  • 启动图标换成新素材:黄色底 + 蓝色渐变三角波浪(自适应图标,前景从原图抠出,圆形 / 方圆形遮罩都不会切到描边;原图存放在 art/launcher-source.png)
  • 播放错误写入诊断信息(错误码、异常类型、播放源类型),本地文件播放失败时明确提示后再转在线播放
  • 作者页、搜索页打开的播放流也支持画中画:小窗按钮可用,开了“切到后台自动进入画中画”时切后台同样进小窗;分享期间不进小窗
  • 重复下载同一个视频时先确认:提示已下载过的清晰度,同清晰度会覆盖原来那份
  • 修复画中画小窗只有声音没有画面:横屏视频的上移留白按整屏高度计算,进小窗后比窗口还大,画面被挤没。小窗内不再留白,卡片尺寸变化时按当前高度重算,且留白不超过卡片高度的一半

v0.9.1

  • 修复中文简介被误判为外语并显示“翻译自中文”:判断语言前剥掉链接、邮箱、@用户名;翻译服务识别出源语言是中文时也不显示翻译行
  • 暂停控制行改为半透明胶囊:后退 / 前进的秒数写在圆弧箭头的圆心里,播放三角改用矢量图标
  • 已下载页面点击视频改为在应用内直接播放本地文件(用下载器授权的 content:// 地址,离线可用),不再拉起外部播放器或回退在线加载
  • 修复播完自动进入下一条后滑不回上一条:放完的视频记录位置改为 0,不再从片尾起播又立刻跳走
  • 修复评论头像错乱:卡片复用时先取消上一条未完成的头像请求;没有头像的显示圆形占位
  • 作者主页显示头像
  • 新启动图标:近白底上青→蓝渐变的圆角播放三角,白色与蓝色两道波浪穿过(矢量自适应图标)

v0.9.0

  • 半屏面板新增「简介」页签:点视频标题打开,显示标题、作者、日期、播放 / 点赞数、标签和正文;简介页可直接切到评论
  • 简介和评论自动翻译为中文(谷歌翻译免费接口):面板打开才请求,结果缓存;可切换原文 / 中文;原文是中文时不显示翻译行;失败时原位显示原因并可重试
  • 面板顶部的把手支持按住下拖,拖过面板高度四分之一或快速下甩即收起,否则弹回
  • 设置新增“翻译”分组:内置谷歌(默认)、DeepL、微软、百度、LibreTranslate,以及自定义接口(地址模板 / 方法 / 请求体 / 请求头 / 字段路径)

v0.8.4

  • 点赞动画素材放慢:每帧 40ms → 70ms(26 帧,1.04s → 1.82s),与收藏动画同节奏;画布由 750×750 重采样为 560×560,与收藏动画一致

v0.8.3

  • 暂停时画面中央的大播放按钮改为左下角进度条上方的小三角(去掉圆圈),左右各加一个后退 / 前进按钮
  • 设置 → 播放新增“前进 / 后退秒数”(5 / 10 / 15 / 30 / 60,默认 15)

v0.8.2

  • 评论面板打开时点击画面改为收起面板(不再暂停视频)
  • 评论面板顶边略微下移,画面随之下移、底边仍贴着面板
  • 设置弹窗限高,与主菜单弹窗相当,内容在弹窗内滚动;取消 / 保存常驻弹窗底部,不随内容滚动
  • 评论面板:点头像或名字进入该用户主页;没有作品的用户主页显示“没有作品”
  • 作者页、搜索页的播放流也有评论按钮和评论面板
  • 作者主页简介默认三行,点击展开全文,滑动作品列表时收起
  • 点赞动画进一步缩小(104dp → 84dp),按钮大小不变
  • 右侧操作栏:按钮之间统一 14dp 间距,图标与文字间距收紧;下载、小窗改用矢量图标,与评论、分享风格一致

v0.8.1

  • 分享改为应用内分享面板:列出能接收链接的应用,点选后直接拉起该应用(QQ 等以自己的小窗卡片盖在视频上,视频继续播放);提供复制链接和系统选择器
  • 移除画中画小窗内的分享按钮
  • 评论输入改为贴在键盘上方的独立输入层,页面和评论面板不再随键盘收缩;点空白处收起,未发送内容保留为草稿

v0.8.0

  • 点赞按钮与动画缩至与收藏按钮同尺寸,赞数贴近爱心
  • 横屏视频画面略微上移,竖屏不变
  • 新增评论:官方评论半屏面板,支持回复,面板顶边对齐画面底边,打开时不影响播放
  • 已下载页面自动补录旧版本(0.7.18 之前)通过系统下载器下载的视频
  • 推荐新增老片穿插:每 12 条一组,组内随机位置插入一条老的优质视频,间隔可设置
  • 推荐榜单全部失败时错误信息带上实际原因
  • 诊断信息改为 txt 文件,可直接以文件分享;保留最近 5 份
  • 设置新增网络分组:手动 HTTP / SOCKS 代理
  • 连接类错误统一提示为“连不上 Iwara,请检查代理 / VPN”

v0.7.26

  • 保存设置时只在推荐候选受影响时重新加载列表,其余设置直接应用到当前卡片

v0.7.25

  • 修复分享面板弹出后视频画面变黑:onPause 改为只暂停不释放播放器

v0.7.24

  • 暂停时中央播放图标改为可在设置中关闭

v0.7.23

  • 画中画小窗新增分享按钮;小窗内翻页时分享目标随之更新
  • 分享面板改由播放页通过 launcher 拉起,分享期间不自动进入小窗
  • 推荐:关注更新不足时自动拉大间隔并按最终显示的一段均匀分布;没有关注更新时列表原样返回

QQ 内“分享成功 / 返回应用”浮层需要接入腾讯 SDK,系统 ACTION_SEND 分享不提供该能力。

v0.7.22

  • 推荐抽页范围改为按接口回传的 count 计算真实页数;空页探测降级为无 count 时的退路
  • date 兜底上限 11000 页(仅用于首次请求前),popularity 策略上限 3000 页
  • 新增 VideoListPage,列表接口同时返回总条数

v0.7.21

  • 抽页上限放宽:最新投稿 8000 页、流行 3000 页、关注存量 200 页;抽页概率改为立方分布
  • 上限自动探测:某页请求成功却为空时将该榜单上限压到该页以下

v0.7.20

  • 「同步点赞记录」「诊断信息」移入设置页 → 维护,点击立即执行
  • 设置页可滚动

v0.7.19

  • 关注作者的更新插在所属分组内的随机位置

v0.7.18

  • 推荐:取消已关注作者的打分加成,改为每 5 条配 1 条关注更新
  • 新增「已下载」页面
  • 「本地收藏」改称「我的收藏」

v0.7.17

  • 点赞 / 收藏改用圆润的爱心与五角星矢量图标,内置 GIF 动画,播在点击位置
  • 点赞动画仅在请求实际发出时播放;收藏不再弹提示

v0.7.16

  • 推荐候选改为每轮在整个存档里随机抽页;补量时继续抽新页并读取关注作者的存量更新
  • 去掉按页码的打分衰减,放缓新鲜度衰减
  • 诊断信息记录抽到的页码

v0.7.15

  • 推荐候选来源重做:新增关注作者更新与最新投稿两个来源,保留热门榜单

v0.7.14

  • 修复候选被“排除已看”过滤光时出现空页面:候选不足时先翻页,再退回看过但未点赞的
  • 修复播放地址过期后黑屏不恢复:监听播放错误并自动重新解析
  • 点赞记录改为后台完整翻页同步;主菜单新增手动同步

v0.7.12

  • 竖滑流缓冲 50 秒 → 25 秒,起播缓冲 2.5 秒 → 1.2 秒;预缓存按网络状况调整
  • 作者主页新增“分享作者”
  • 修复作者页关注后返回视频流关注按钮未更新

v0.7.11

  • 搜索页“角色名”改为“标签”,支持多标签同时搜索

v0.7.10

  • 暂停时隐藏信息栏和操作栏,只保留进度条

v0.7.9

  • 修复「已关注用户」只显示 50 位
  • 搜索改为独立结果页,分视频名 / 标签 / 作者名三个列表
  • 预检全部失败时直接显示未验证的视频并提示
  • 诊断信息新增加载线索
  • 新增分享按钮

v0.7.8

  • 推荐翻页继续使用推荐候选,用完重新生成
  • 点赞后立即计入已看;刷新推荐时同步官方点赞列表
  • 首屏边验证边上屏;可播放验证与榜单请求增加时间预算
  • 加密会话、Media3 缓存索引、浏览历史数据库改为后台预热

v0.7.6

  • 修复返回页面时的闪退:网络客户端在后台清理
  • 统一子页面返回与播放生命周期;各子页面使用 AndroidX 返回分发
  • 新增“诊断信息”

v0.6.3

  • 顶部排序栏统一为“最新 / 流行 / 人气”
  • 全 App 单一播放器所有权

v0.6.2

  • 作者主页作品列表显示真实缩略图

v0.6.1

  • “排除已看视频”默认开启;新增独立 seen_videos 表
  • 修复多个 Activity 同时打开 Media3 缓存目录导致的闪退

v0.6.0

  • 应用内检查更新;GitHub Actions 自动发布 Release APK

v0.5.0

  • 作者主页、作者作品播放流
  • 关注 / 好友同步;已关注用户列表

v0.4.0

  • “自动跳过已看”改为“刷新推荐时排除已看”
  • 新增可播放验证(PlayableVideoGate)与 Media3 磁盘预缓存

v0.3.x

  • 重构播放器生命周期;decoder fallback 与卡死恢复
  • 点赞与本地收藏分离;按住 2× 加速
  • 浅蓝色系 UI;launcher 图标;签名 APK 构建

v0.2.0

  • Iwara 登录与 Token 管理、官方点赞同步
  • 浏览历史、搜索、下载、画中画、本地推荐算法、自动下一条

说明

这是第三方客户端,不隶属于 Iwara。

Iwara API 属于站点内部接口,后续若接口、Cloudflare 策略或视频源签名方式发生变化,相关网络层可能需要继续适配。

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages