bilibili / DanmakuFlameMaster

Android开源弹幕引擎·烈焰弹幕使 ~
http://app.bilibili.com/
Apache License 2.0
9.54k stars 2.1k forks source link

增加弹幕倍速功能 #414

Open luern0313 opened 5 years ago

luern0313 commented 5 years ago

    不更改现有接口和外部调用的情况下修改timer源码来支持弹幕动态倍速。     currMillisecond用来确定弹幕的时间,如在外部updateTimer回调中手动更改currMillisecond来更改弹幕时间,即把currMillisecond加上lastInterval乘以视频速度-1的差(因为在回调之前已经加上了一个lastInterval了),并不能实现弹幕倍速,因为会出现一个问题:下次回调时,由于lastInterval是根据新的currMillisecond减去之前的currMillisecond得出的,但之前的currMillisecond是经过修改的,故lastInterval并不是真实的现实间隔时间,currMillisecond向前或向后修改,之后的lastInterval就会相应的增加或减少,导致弹幕的速度会慢慢的趋近于正常速度。     我构想的解决方法是,lastInterval并不由currMillisecond计算得出,而是由类内获取系统时间,算出现实时间的间隔,并且currMillisecond由这个间隔和视频倍速算出弹幕正确的时间。     这样,传入的curr参数就只剩一个作用:判断视频是否进行了跳转。当curr的间隔和类内获取当前时间的间隔差值超过一定值时,就可以认为视频进行了跳转,弹幕也需要跳转到新的时间。在弹幕开始播放时,我储存了第一个curr的数值,由新的curr减去第一个curr,就能得出视频当前时间,直接让currMillisecond等于这个值就行。     如何设置弹幕倍速可以参考以下方式:

boolean isSpeedJustChange = false;
float videoSpeed = 1.0f;

......
changeSpeed.setOnClick....... {
    //这里更改速度
    isSpeedJustChange = true;
    videoSpeed = xxx;
}

......
updateTimer... {
    //下一次updateTimer时调用方法更改速度
    if(isSpeedJustChange) {
        isSpeedJustChange = false;
        timer.setSpeed(videoSpeed);
    }
}
luern0313 commented 5 years ago

没人吗。。

DorisGM commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

DorisGM commented 5 years ago

没人吗。。 这个是不是还没合并到主干里面去?

luern0313 commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

luern0313 commented 5 years ago

没人吗。。 这个是不是还没合并到主干里面去?

好像没官方的人看pr申请。。

DorisGM commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

luern0313 commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

能详细说说吗?

DorisGM commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

能详细说说吗?

比如在00:12已经播了 “很好很好”这个弹幕,他会在00:12这之后重复播 三次“很好很好”, 可能是时间计算上有细微的偏差 导致又播了两到三次

luern0313 commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

能详细说说吗?

比如在00:12已经播了 “很好很好”这个弹幕,他会在00:12这之后重复播 三次“很好很好”, 可能是时间计算上有细微的偏差 导致又播了两到三次

是所有弹幕都会重复还是只有个别的?我这怎么没出现这个问题。。

DorisGM commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

能详细说说吗?

比如在00:12已经播了 “很好很好”这个弹幕,他会在00:12这之后重复播 三次“很好很好”, 可能是时间计算上有细微的偏差 导致又播了两到三次

是所有弹幕都会重复还是只有个别的?我这怎么没出现这个问题。。

个别,不是所有。我看看有没有复现规律。

luern0313 commented 5 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

能详细说说吗?

比如在00:12已经播了 “很好很好”这个弹幕,他会在00:12这之后重复播 三次“很好很好”, 可能是时间计算上有细微的偏差 导致又播了两到三次

是所有弹幕都会重复还是只有个别的?我这怎么没出现这个问题。。

个别,不是所有。我看看有没有复现规律。

好吧。。我这也再看看

stayli117 commented 5 years ago

您好 请问 测试过这种条件吗 前一屏幕的弹幕全部展示完之后,等待2秒后, 后一屏幕的出来。

luern0313 commented 5 years ago

您好 请问 测试过这种条件吗 前一屏幕的弹幕全部展示完之后,等待2秒后, 后一屏幕的出来。

emmm我没听懂

stayli117 commented 5 years ago

您好 请问 测试过这种条件吗 前一屏幕的弹幕全部展示完之后,等待2秒后, 后一屏幕的出来。

emmm我没听懂

原来用这样类似的方式改过一次,然后其他情况都行,只有这样一种情况有问题,查了一下原因,源码里有段判断当前展示的情况,完全没有,就会释放。之后就会出现问题,在这样一个场景中, 视频的播放的一个过程中,中间有一段时间完全没有弹幕,然后后面再出来的弹幕,就会一直重复的播放。

luern0313 commented 5 years ago

您好 请问 测试过这种条件吗 前一屏幕的弹幕全部展示完之后,等待2秒后, 后一屏幕的出来。

emmm我没听懂

原来用这样类似的方式改过一次,然后其他情况都行,只有这样一种情况有问题,查了一下原因,源码里有段判断当前展示的情况,完全没有,就会释放。之后就会出现问题,在这样一个场景中, 视频的播放的一个过程中,中间有一段时间完全没有弹幕,然后后面再出来的弹幕,就会一直重复的播放。

那看来倍速这个只能等官方做了。。

xiaoxinYue commented 4 years ago

都没人维护了吧,官方怎么会有人做

gityan commented 4 years ago

遇到同样的问题,想改变timer的速度但比较麻烦,后来想了一个办法绕了过去。 其实最终要实现的效果是2倍速下,原本在100s处显示的弹幕在第50s显示。时间流逝的速度既然改不了,那么可以改变相对于这个流速的位置。在添加弹幕的时候修改弹幕时间 danmaku.time = item.position * 1000/speed 设置speed的时候,清空已经添加的弹幕,重新add弹幕。然后seek一下。seek方法要改成 danmakuView.seekTo(position/speed)。凑合着用吧。

yzhiwu commented 3 years ago

简单做了个修改,可以试下, mSpeed是倍速率,思路是根据倍速率改变timer的变化时间,并记录增量,在弹幕未显示时做同步。

    private long mSpeedOffsetNoRender = 0L;
    private long mSpeedOffsetRender = 0L;
    private float mSpeed = 1.0F;

    private final long syncTimer(long startMS) {
        ...
        } else if (!mDanmakusVisible || mRenderingState.nothingRendered || mInWaitingState) {
            timer.update(time + mSpeedOffsetNoRender + mSpeedOffsetRender);
            mSpeedOffsetNoRender += mFrameUpdateRate * (mSpeed - 1);
            mRemainingTime = 0;
            if (mCallback != null) {
                mCallback.updateTimer(timer);
            }
        } else {
            long gapTime = time - timer.currMillisecond;
            long averageTime = Math.max(mFrameUpdateRate, getAverageRenderingTime());
            if (gapTime > 2000 || mRenderingState.consumingTime > mCordonTime || averageTime > mCordonTime) {
                d = gapTime;
                gapTime = 0;
            } else {
                d = averageTime + gapTime / mFrameUpdateRate;
                d = Math.max(mFrameUpdateRate, d);
                d = Math.min(mCordonTime, d);
                long a = d - mLastDeltaTime;
                if (a > 3 && a < 8 && mLastDeltaTime >= mFrameUpdateRate && mLastDeltaTime <= mCordonTime) {
                    d = mLastDeltaTime;
                } else {
                    mSpeedOffsetRender += d * (mSpeed - 1);
                    d = (int) (d * mSpeed);
                }
                gapTime -= d;
                mLastDeltaTime = d;
            }
            ...
        }

        mInSyncAction = false;
        return d;
    }

    // handleMessage的seek时置0.
    case SEEK_POS:
                if (what == SEEK_POS) {
                    ...
                    mSpeedOffsetRender = 0L;
                    mSpeedOffsetNoRender = 0L;
                    ...
                }
NaughtyHotpot commented 2 years ago

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

没人吗。。

大神 请问你那边测试稳定吗 会引发其他问题吗?

我这里有简单的测试,目前没有发现任何问题

好像会出现弹幕偶尔会重复播放

请问这个问题你解决了吗😆 请教一下

LukeLuAndroid commented 2 years ago

item

我也想到了,看到你的答案我更确信方案可行。

Lscyzq commented 6 months ago

三生有幸,见到luern0313

Lscyzq commented 6 months ago

怎么都是说了但没有完全说啊!