2021最新电视直播源m3u(iptv 2021 直播源)

  • 什么是视频封装
  • mp4 format信息
  • mp4 streams信息
  • ts文件format信息
  • ts文件stream信息
  • 使用ffmpeg制作多track视频
  • ExoPlayer track selection
  • ExoPlayer获取 tracks信息
  • 修改Track Selection参数
  • 停止某个Track Type
  • 指定某一个特殊的tracks
  • 总结
  • 参考文献

什么是视频封装

在开始介绍音视频的Track Selection之前,我们先了解一下视频封装,比如常见的mp4文件, ts文件,就是一个视频封装文件,mp4和ts就是一种封装格式,这里之所以选择mp4和ts这两种封装格式,是因为这两种封装格式具有代表性,前者适用于点播,后者常用语广播电视,当然也不是绝对的。

mp4本地文件就不说了,看一下新浪微博的点播视频,用的就是mp4

021最新电视直播源m3u(iptv

ts流一般用广播电视,IPTV 这个是网上的一个IPTV的源,从里面找了一个CCTV4源。

http://117.169.120.140:8080/live/cctv-4/.m3u8

m3u8文件其实就是一个文本文件,它是苹果出的HLS(HTTP Live Stream)的一部分。

HLS 的工作原理是把整个流分成一个个小的基于 HTTP 的文件来下载,每次只下载一些.

下面就是一个m3u8文件,可以看到里面包含了好几个ts文件,每个ts文件对应的是一小段片段。如果是直播,会定时,请求这个m3u8文件,然后下载里面的ts片段并播放。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:1648731453
#EXTINF:10.0,5260052
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133801_133811.ts
#EXTINF:10.0,5380372
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133811_133821.ts
#EXTINF:10.0,5312504
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133821_133831.ts
#EXTINF:10.0,5333936
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133831_133841.ts
#EXTINF:10.0,5366272
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133841_133851.ts
#EXTINF:10.0,5317204
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133851_133901.ts
#EXTINF:10.0,5319272
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133901_133911.ts
#EXTINF:10.0,5330928
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133911_133921.ts
#EXTINF:10.0,5354052
http://117.169.120.140:8080/wh7f454c46tw2466423005_613384962/live/cctv-4/HD-4000k-1080P-cctv4_20220426_133921_133931.ts

我们都知道,文件的扩展名是用来识别文件类型的。通过给他指定扩展名,我们可以告诉自己,也可以告诉操作系统用什么打开方式打开这个文件。

比如一个mp4后缀名的文件,打开方式里会有一些默认的视频软件。

021最新电视直播源m3u(iptv

同样一个mp3后缀名的文件,打开方式里也会有一些默认的音频软件。

021最新电视直播源m3u(iptv

文件的后缀名是可以随便改的,Linux或者mac上可以用file命令查看实际的文件格式。

? file audio.mp3
audio.mp3: Audio file with ID3 version 2.3.0, contains:MPEG ADTS, layer III, v1, 320 kbps, 44.1 kHz, Stereo
? file run_android_emulator.mp4
run_android_emulator.mp4: ISO Media, MP4 v2 [ISO 14496-14]

它其实是利用文件头标识来进行文件类型判断的,下面是mp3和mp4对应的文件头标识。

扩展名

文件头标识(HEX)

文件描述

MP3

49 44 33

MPEG-1 Audio Layer 3 (MP3) audio file

mp4

00 00 00 18 66 74 79 70 33 67 70 35

MPEG-4 video files

更直观的我们可以通过hexdump命令来查看文件的十六进制形式。

021最新电视直播源m3u(iptv

一个封装文件或者一个封装格式通常由下面的元素构成:

  • 文件标识头
  • 多媒体信息(多媒体元数据)
  • 音视频(字幕)轨
  • 视频索引块组成

整个解封装的流程:

  1. 读取文件头判断文件格式,比如mp4, ts,然后选择对应的Extractor.
  2. 解析多媒体信息
  3. 解析视频帧的索引块
  4. 最后根据索引去定位并读取音视频数据。

如下图:

021最新电视直播源m3u(iptv

image-20220426192634200

下面我们用一种稍微直观点的方式,看一下封装文件中包含了哪些信息。

ffprobe是ffmpeg中的一个库,我们借助这个工具可以看一下一个封装文件中的信息。

mp4 format信息

ffprobe -show_format run_android_emulator.mp4 -print_format json
{
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'run_android_emulator.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp41mp42isom
    creation_time   : 2021-10-30T04:16:21.000000Z
  Duration: 00:02:24.50, start: 0.000000, bitrate: 2168 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
      creation_time   : 2021-10-30T04:16:21.000000Z
      handler_name    : Core Media Audio
    Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1280x720 [SAR 1:1 DAR 16:9], 2032 kb/s, 30 fps, 30 tbr, 30k tbn, 60k tbc (default)
    Metadata:
      creation_time   : 2021-10-30T04:16:21.000000Z
      handler_name    : Core Media Video
    "format": {
        "filename": "run_android_emulator.mp4", //文件名称
        "nb_streams": 2, //视频av stream的个数
        "nb_programs": 0,
        "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
        "format_long_name": "QuickTime / MOV",
        "start_time": "0.000000",
        "duration": "144.500000",
        "size": "39162388",
        "bit_rate": "2168159",
        "probe_score": 100,
        "tags": {
            "major_brand": "mp42",
            "minor_version": "1",
            "compatible_brands": "mp41mp42isom",
            "creation_time": "2021-10-30T04:16:21.000000Z"
        }
    }
}

mp4 streams信息

ffprobe run_android_emulator.mp4 -show_streams -print_format json
{
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'run_android_emulator.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp41mp42isom
    creation_time   : 2021-10-30T04:16:21.000000Z
  Duration: 00:02:24.50, start: 0.000000, bitrate: 2168 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
      creation_time   : 2021-10-30T04:16:21.000000Z
      handler_name    : Core Media Audio
    Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1280x720 [SAR 1:1 DAR 16:9], 2032 kb/s, 30 fps, 30 tbr, 30k tbn, 60k tbc (default)
    Metadata:
      creation_time   : 2021-10-30T04:16:21.000000Z
      handler_name    : Core Media Video
    "streams": [
        {
            "index": 0,
            "codec_name": "aac",
            "codec_long_name": "AAC (Advanced Audio Coding)",
            "profile": "LC",
            "codec_type": "audio",
            "codec_time_base": "1/48000",
            "codec_tag_string": "mp4a",
            "codec_tag": "0x6134706d",
            "sample_fmt": "fltp",
            "sample_rate": "48000",
            "channels": 2,
            "channel_layout": "stereo",
            "bits_per_sample": 0,
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/48000",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 6936000,
            "duration": "144.500000",
            "bit_rate": "127307",
            "max_bit_rate": "128000",
            "nb_frames": "6776",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0
            },
            "tags": {
                "creation_time": "2021-10-30T04:16:21.000000Z",
                "language": "eng",
                "handler_name": "Core Media Audio"
            }
        },
        {
            "index": 1,
            "codec_name": "h264",
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
            "profile": "High",
            "codec_type": "video",
            "codec_time_base": "1/60",
            "codec_tag_string": "avc1",
            "codec_tag": "0x31637661",
            "width": 1280,
            "height": 720,
            "coded_width": 1280,
            "coded_height": 720,
            "has_b_frames": 0,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "16:9",
            "pix_fmt": "yuv420p",
            "level": 31,
            "color_range": "tv",
            "color_space": "bt709",
            "color_transfer": "bt709",
            "color_primaries": "bt709",
            "chroma_location": "left",
            "field_order": "progressive",
            "refs": 1,
            "is_avc": "true",
            "nal_length_size": "4",
            "r_frame_rate": "30/1",
            "avg_frame_rate": "30/1",
            "time_base": "1/30000",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 4335000,
            "duration": "144.500000",
            "bit_rate": "2032370",
            "bits_per_raw_sample": "8",
            "nb_frames": "4335",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0
            },
            "tags": {
                "creation_time": "2021-10-30T04:16:21.000000Z",
                "language": "und",
                "handler_name": "Core Media Video"
            }
        }
    ]
}

ts文件format信息

"format": {
        "filename": "0_00_192.tts",
        "nb_streams": 31,
        "nb_programs": 5,
        "format_name": "mpegts",
        "format_long_name": "MPEG-TS (MPEG-2 Transport Stream)",
        "start_time": "63983.328467",
        "duration": "193.067422",
        "size": "735749184",
        "bit_rate": "30486725",
        "probe_score": 50
    }

ts文件stream信息

ts的stream信息太多了,这里就不贴了。

使用ffmpeg制作多track视频

? ffmpeg -i run_android_emulator.mp4 -i video_track.mp4 -i audio.mp3 -i audio2.mp3 -map 0:v -map 1:v -map 2:a -map 3:a -c copy -shortest output_video_audio_track.mp4

上面的命令就是将run_android_emulator.mp4和video_track.mp4这两个视频以及audio.mp3 和 audio2.mp3这两个音频合并成一个mp4视频, 这个过程不需要重新编码,所以速度非常的快。

然后再用ffmpeg查看一下合并成的mp4文件信息:

? ffmpeg -i output_video_audio_track.mp4 -hide_banner
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_video_audio_track.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.5.100
  Duration: 00:00:25.03, start: 0.000000, bitrate: 2923 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 2052 kb/s, 30 fps, 30 tbr, 30k tbn (default)
    Metadata:
      handler_name    : Core Media Video
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 480x360 [SAR 1:1 DAR 4:3], 413 kb/s, 30 fps, 30 tbr, 30k tbn (default)
    Metadata:
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](und): Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 320 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:3[0x4](und): Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]

ExoPlayer track selection

前面介绍了一下音视频文件关于封装的一些基础知识,大概知道了音视频中Track的概念,下面就介绍一下Track Selection并且它在ExoPlayer中的运用。Track Selection决定了播放器去播哪个track, 对应上面的stream。比如一个视频文件里有多个video track, 多个audio track,或者多个字幕track.播视频的时候,你需要选择播哪个video track,哪个audio track和哪个字幕track. 在ExoPlayer使用TrackSelectionParameters 这个类负责Track Selection的一些设置, 也可以给track selection添加限制规则。

ExoPlayer获取 tracks信息

ExoPlayer需要prepare后,才能获取到当前视频可用的tracks信息,可以通过Player.Listener.onTracksInfoChanged

监听tracks信息的变化。这个触发的时机是:

  • 当Player preparation完成。
  • 当可以的tracks或者selected的tracks信息发生变化。
  • 当playlist item发生变化。
player.addListener(new Player.Listener() {
  @Override
  public void onTracksInfoChanged(TracksInfo tracksInfo) {
    for (TracksInfo.TrackGroupInfo groupInfo : tracksInfo.getTrackGroupInfos()) {
        @C.TrackType int trackType = groupInfo.getTrackType();
        boolean trackInGroupIsSelected = groupInfo.isSelected();
        boolean trackInGroupIsSupported = groupInfo.isSupported();
        Log.d(TAG, "TrackGroupInfo trackType: " + trackType);
        Log.d(TAG, "TrackGroupInfo trackInGroupIsSelected: " + trackInGroupIsSelected);
        Log.d(TAG, "TrackGroupInfo trackInGroupIsSupported: " + trackInGroupIsSupported);
        TrackGroup group = groupInfo.getTrackGroup();
        for (int i = 0; i < group.length; i++) {
          boolean isSupported = groupInfo.isTrackSupported(i);
          boolean isSelected = groupInfo.isTrackSelected(i);
          Format trackFormat = group.getFormat(i);
          Log.d(TAG, "TrackGroup isSupported: " + isSupported);
          Log.d(TAG, "TrackGroup isSelected: " + isSelected);
          Log.d(TAG, "TrackGroup trackFormat: " + trackFormat.toString());
        }
      }
  }
});

如果想获取当前的TracksInfo可以使用下面的方法

player.getCurrentTracksInfo()
  • TracksInfo包含了一组TrackGroupInfo` ,每个TrackGroupInfo包含了Track的type, format详情,播放器是否支持当前track,是否被select.进一步的解释是,TrackGroupInfo对应的是一组视频轨、或者音频轨、或者字幕轨。TrackGroupInfo再往下分是TrackGroup,例如TrackGroupInfo对应的是一组视频轨,那么TrackGroup就是这一组视频轨中的某一个视频轨。
021最新电视直播源m3u(iptv

  • 一个track是supported表示Playe能够decode和render这个track.
  • 一个track是selected表示track selector选择这个track播放,track select的配置放在TrackSelectionParameters中。需要注意如果是多条track的TrackGroup被selected,那么播放器会自适应播放(比如,多个video track 有不同的码率)。注释,虽然TrackGourp是selected,但是其真正select的是group里的一个track select.

修改Track Selection参数

Selection流程可以通过Player.setTrackSelectionParameters方法,设置 TrackSelectionParameters类。这些更新可以在播放前或者播放过程中都可以生效。建议在设置Track Selection的时候,先获取一下当前的配置,然后在当前配置的基础上去修改。

player.setTrackSelectionParameters(
    player.getTrackSelectionParameters()
        .buildUpon()
        .setMaxVideoSizeSd()
        .setPreferredAudioLanguage("hu")
        .build());

停止某个Track Type

比如关闭Video track 这个类型,这样就只有音频能播放了,这样就可以试下Audio Only的功能了,比如如果想实现Android版B站有后台播放的功能,直接可以将Video Track设置为Disable就可以。

player.setTrackSelectionParameters(
    player.getTrackSelectionParameters()
        .buildUpon()
        .setDisabledTrackTypes(ImmutableSet.of(C.TRACK_TYPE_VIDEO))
        .build());

还有另外一种方式,可以实现这个功能,通过创建一个空的video overrides, 这个overrides下面再介绍,相当于指定某一个track,其他的track就不会被selected了。

TrackSelectionOverrides overrides =
    new TrackSelectionOverrides.Builder()
        .addOverride(
             new TrackSelectionOverride(
                disabledTrackGroup,
                /* select no tracks for this group */ ImmutableList.of()))
        .build();
player.setTrackSelectionParameters(
    player.getTrackSelectionParameters()
        .buildUpon().setTrackSelectionOverrides(overrides).build());

指定某一个特殊的tracks

指定某一个特殊的TrackGroup为Selected Tracks.

TrackSelectionOverrides overrides =
    new TrackSelectionOverrides.Builder()
        .setOverrideForType(new TrackSelectionOverride(audioTrackGroup))
        .build();
player.setTrackSelectionParameters(
    player.getTrackSelectionParameters()
        .buildUpon().setTrackSelectionOverrides(overrides).build());

总结

ExoPlayer支持本地音视频文件的播放,比如上面用ffmpeg生成了一个多track视频文件。同时,ExoPlayer也支持一些流媒体协议比如:DASH,HLS等,如下是ExoPlayer支持的流媒体协议。

021最新电视直播源m3u(iptv

这些流媒体里同样可以获取到Track信息和Track Selection.具体这里就不详细介绍了,有兴趣的可以研究一下。

参考文献

  • ExoPlayer官方文档
  • 走进音视频的世界
  • 利用文件头标志判断文件类型
  • MpegTS流解复用程序实现
  • ts流格式解析
  • ts格式介绍
  • ffmpeg、ffplay、ffprobe命令使用
  • FFmpeg 视频处理入门教程
  • ExoPlay实现框架
  • Sample地址
本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 sumchina520@foxmail.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.yiheng8.com/166151.html