在flutter中,如何显示音频的所有字幕,并根据音频自动滚动突出显示当前字幕
Flutter 有一些插件(flutter_lyric、christian_lyrics 等...),但这些插件不好,无法自定义,有平台异常,错误,自动滚动不起作用,与音频不同步等.....
那么我该怎么做呢?它应该如下图所示!
目前没有可用的插件。如何创建这种功能......?
使用音频插件:just_audio:^0.9.34
在flutter中,目前没有可用的插件。可用的插件无法执行此类功能,你应该从头开始
使用我的代码来获得这种功能
使用的插件:
srt_parser_2:^2.0.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;
}
}
如果有任何问题请评论,让我知道!
我在同一个项目中需要你的帮助 如果可以的话请联系我。 tno2607@g 邮件。 com 谢谢!