显示音频的所有字幕,并根据音频突出显示当前字幕,并在 flutter 中自动滚动

问题描述 投票:0回答:2

在flutter中,如何显示音频的所有字幕,并根据音频自动滚动突出显示当前字幕

Flutter 有一些插件(flutter_lyric、christian_lyrics 等...),但这些插件不好,无法自定义,有平台异常,错误,自动滚动不起作用,与音频不同步等.....

那么我该怎么做呢?它应该如下图所示!

目前没有可用的插件。如何创建这种功能......?

使用音频插件:just_audio:^0.9.34

flutter
2个回答
1
投票

在flutter中,目前没有可用的插件。可用的插件无法执行此类功能,你应该从头开始

使用我的代码来获得这种功能

使用的插件:

  1. srt_parser_2:^2.0.2

  2. 只是_音频:^0.9.34

使用上面的插件我们可以实现它

SRT

static String subtitleSrt= '''1
00:00:03,400 --> 00:00:06,177
In this lesson, we're going to be talking about finance And 
sjhwsd wjhd qwnjdvbqwe dfwedfwe fwejfberfg 
regjh ergv ergberg ergbrtg rth rt j yu jjkgndfm 
vdjhvbd xcasjhcdsem cfhcfcf dejcfden vbcdswvn sdvsdbv.

2
00:00:06,177 --> 00:00:10,009
one of the most important aspects
of finance is interest.

3
00:00:10,009 --> 00:00:13,655
When I go to a bank or some
other lending institution

4
00:00:13,655 --> 00:00:17,720
to borrow money, the bank is happy
to give me that money. But then I'm

5
00:00:17,900 --> 00:00:21,480
going to be paying the bank for the
privilege of using their money. And that

6
00:00:21,660 --> 00:00:26,440
amount of money that I pay the bank is
called interest. Likewise, if I put money

7
00:00:26,620 --> 00:00:31,220
in a savings account or I purchase a
certificate of deposit, the bank just

8
00:00:31,300 --> 00:00:35,800
doesn't put my money in a little box
and leave it there until later. They take

9
00:00:35,800 --> 00:00:40,822
my money and lend it to someone
else. So they are using my money.

10
00:00:40,822 --> 00:00:44,400
The bank has to pay me for the privilege
of using my money.

11
00:00:44,400 --> 00:00:48,700
Now what makes banks
profitable is the rate

12
00:00:48,700 --> 00:00:53,330
that they charge people to use the bank's
money is higher than the rate that they

13
00:00:53,510 --> 00:01:00,720
pay people like me to use my money. The
amount of interest that a person pays or

14
00:01:00,800 --> 00:01:06,640
earns is dependent on three things. It's
dependent on how much money is involved.

15
00:01:06,820 --> 00:01:11,300
It's dependent upon the rate of interest
being paid or the rate of interest being

16
00:01:11,480 --> 00:01:17,898
charged. And it's also dependent upon
how much time is involved. If I have

17
00:01:17,898 --> 00:01:22,730
a loan and I want to decrease the amount
of interest that I'm going to pay, then

18
00:01:22,800 --> 00:01:28,040
I'm either going to have to decrease how
much money I borrow, I'm going to have

19
00:01:28,220 --> 00:01:32,420
to borrow the money over a shorter period
of time, or I'm going to have to find a

20
00:01:32,600 --> 00:01:37,279
lending institution that charges a lower
interest rate. On the other hand, if I

21
00:01:37,279 --> 00:01:41,480
want to earn more interest on my
investment, I'm going to have to invest

22
00:01:41,480 --> 00:01:46,860
more money, leave the money in the
account for a longer period of time, or

23
00:01:46,860 --> 00:01:49,970
find an institution that will pay
me a higher interest rate.''';

playerPage.dart


class PlayerPage extends StatefulWidget {
  @override
  _PlayerPageState createState() => _PlayerPageState();
}

class _PlayerPageState extends State<PlayerPage> {
  // audio player implementation

  //  ...............

  //

 List<Subtitle> subtitlesData = parseSrt(subtitleSrt);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SingleChildScrollView(
            child: Column(
      children: [
        // audio player widget

        Container(
            height: 91.h,
            width: 310.w,
            child: StreamBuilder<PositionData>(
              stream: _playerStore.positionDataStream,
              builder: (context, snapshot) {
                final positionData = snapshot.data;
                return SeekBar(
                  duration: positionData?.duration ?? Duration.zero,
                  position: positionData?.position ?? Duration.zero,
                  bufferedPosition:
                      positionData?.bufferedPosition ?? Duration.zero,
                  onChangeEnd: _playerStore.player.seek,
                );
              },
            )),

        // Subtitle widget

        StreamBuilder<PositionData>(
          stream: _playerStore.positionDataStream,
          builder: (context, snapshot) {
            final positionData = snapshot.data;

            return SubtitleBox(
              subtitles: subtitlesData,
              currentDuration: positionData?.duration.inMilliseconds ??
                  Duration.zero.inMilliseconds,
              currentPosition: positionData?.position.inMilliseconds ??
                  Duration.zero.inMilliseconds,
            );
          },
        )
      ],
    )));
  }
}


字幕框.dart


import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:srt_parser_2/srt_parser_2.dart';

import '../theme/theme.dart';

class SubtitleBox extends StatefulWidget {
  final List<Subtitle> subtitles;
  final int currentPosition;
  final int currentDuration;

  SubtitleBox({
    required this.subtitles,
    required this.currentPosition,
    required this.currentDuration,
  });

  @override
  _SubtitleBoxState createState() => _SubtitleBoxState();
}

class _SubtitleBoxState extends State<SubtitleBox> {
  ScrollController _scrollController = ScrollController();
  Subtitle? _currentSubtitle;

  @override
  void didUpdateWidget(SubtitleBox oldWidget) {
    super.didUpdateWidget(oldWidget);
    _scrollToCurrentSubtitle();
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    _currentSubtitle = _getCurrentSubtitle(widget.currentPosition);

    return SizedBox(
      height: 300, // Adjust the height as per your requirements
      child: ListView.builder(
        controller: _scrollController,
        itemCount: widget.subtitles.length,
        // itemExtent: 80, // Adjust the item extent as per your requirements
        itemBuilder: (context, index) {
          final subtitle = widget.subtitles[index];
          return Text(
            subtitle.rawLines.join(),
            style: TextStyle(
              fontSize: subtitle == _currentSubtitle ? 18.sp : 14.sp,
              fontWeight: subtitle == _currentSubtitle
                  ? FontWeight.w900
                  : FontWeight.w500,
              color: subtitle == _currentSubtitle
                  ? MainTheme.redTypeColor
                  : MainTheme.blackTypeColor,
            ),
          );
        },
      ),
    );
  }

  void _scrollToCurrentSubtitle() {
    if (_currentSubtitle != null) {
      int subtitleIndex = widget.subtitles.indexOf(_currentSubtitle!);
      if (subtitleIndex != -1) {
        double scrollOffset = subtitleIndex * 40; // Adjust based on itemExtent
        _scrollController.animateTo(
          scrollOffset,
          duration: const Duration(milliseconds: 300),
          curve: Curves.easeInOut,
        );
      }
    }
  }

  Subtitle? _getCurrentSubtitle(int currentPosition) {
    for (int i = 0; i < widget.subtitles.length; i++) {
      if (currentPosition >=
              widget.subtitles[i].range.begin.milliseconds.inMilliseconds &&
          currentPosition <=
              widget.subtitles[i].range.end.milliseconds.inMilliseconds) {
        return widget.subtitles[i];
      }
    }
    return null;
  }
}

如果有任何问题请评论,让我知道!


0
投票

我在同一个项目中需要你的帮助 如果可以的话请联系我。 tno2607@g 邮件。 com 谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.