You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用youtube_explode_dart仅下载YouTube音频流的指定片段

基于youtube_explode_dart实现YouTube音频指定片段下载方案

实现原理

YouTube的媒体流支持 HTTP Range请求,你可以先通过音频流的总时长、总大小计算出你需要的时间段对应的字节偏移范围,直接请求这个范围的内容即可,不需要全量下载。

完整实现代码

首先将时间参数转为Duration类型,计算对应字节范围后直接请求分片:

import 'package:youtube_explode_dart/youtube_explode_dart.dart';
import 'dart:io';

void main() async {
  var yt = YoutubeExplode();
  var id = "aboZctrHfK8";
  var file = File("myCroppedSong.mp4");
  // 时间参数转成Duration方便计算
  var start = Duration(milliseconds: 2000);
  var end = Duration(milliseconds: 5000);
  var targetDuration = end - start;

  // 获取音频流信息
  var manifest = await yt.videos.streamsClient.getManifest(id);
  var audio = manifest.audioOnly.first;
  // 音频总时长
  var totalDuration = audio.duration!;
  // 音频总字节数
  var totalBytes = audio.size.totalBytes;
  // 计算起始和结束字节偏移,预留冗余避免切到关键帧导致文件损坏
  var startBytes = (start.inMicroseconds / totalDuration.inMicroseconds * totalBytes).floor();
  // 多申请128KB冗余,保证帧数据完整
  var endBytes = (end.inMicroseconds / totalDuration.inMicroseconds * totalBytes).ceil() + 131072;
  // 字节范围超过总大小则取总大小
  if (endBytes > totalBytes) endBytes = totalBytes;

  // 直接请求指定范围的字节流
  var audioStream = yt.videos.streamsClient.get(audio, start: startBytes, end: endBytes);
  var output = file.openWrite(mode: FileMode.writeOnlyAppend);
  await for (final data in audioStream) {
    output.add(data);
  }
  await output.close();
  yt.close();
}

扩展方法封装(实现你预期的调用形式)

你可以把上面的逻辑封装为StreamClient的扩展方法,就能实现audioStream.subset(start, end)的调用效果:

extension StreamSubset on StreamClient {
  Stream<List<int>> subset(StreamInfo info, Duration start, Duration end) {
    var totalDuration = info.duration!;
    var totalBytes = info.size.totalBytes;
    var startBytes = (start.inMicroseconds / totalDuration.inMicroseconds * totalBytes).floor();
    var endBytes = (end.inMicroseconds / totalDuration.inMicroseconds * totalBytes).ceil() + 131072;
    if (endBytes > totalBytes) endBytes = totalBytes;
    return get(info, start: startBytes, end: endBytes);
  }
}

注意事项

  • 直接下载的分片文件开头可能存在不完整的音频帧,建议下载完成后用ffmpeg做一次快速裁剪,保证文件可正常播放,此时文件体积已经很小,裁剪耗时可以忽略:
FlutterFFmpeg _flutterFFmpeg = FlutterFFmpeg();
await _flutterFFmpeg.executeWithArguments([
      "-v", "error",
      "-ss", "0",
      "-t", targetDuration.inSeconds.toString(),
      "-i", file.path,
      "-acodec", "copy", "finalSong.mp4"]);
  • 可以根据音质需求选择码率更低的音频流,不用默认取audioOnly.first,进一步加快下载速度。

内容的提问来源于stack exchange,提问作者Jérémy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:54:06