gpt4 book ai didi

Ffmpeg 和 ffprobe 未在 m3u8 文件中显示字幕流

转载 作者:行者123 更新时间:2023-12-04 23:20:35 25 4
gpt4 key购买 nike

我正在尝试从 m3u8 播放列表文件(在简单的 HLS 中)获取带有音频、视频和字幕的 mp4 视频。
我设法提取了视频和音频流,因为它们相对容易:根据 ffprobe,输入 m3u8 包含 3 个不同的程序,而第三个程序(称为 Program 2)是我需要的,因为它同时包含最高质量的视频和英语最高质量的音频。
所以,我真正在做的是

ffmpeg -i "blahblah.m3u8" -c copy -map 0:p:2:v:0 -map 0:p:2:a:m:language:eng -map 0:s:0 "output.mp4"
这意味着:为第三个(索引 2)节目选择第一个视频流,并从同一个第三个(索引 2)节目中选择英语音频流。
我的问题是:我似乎找不到两个字幕流。
m3u8 有两个字幕:英语和西类牙语,正如您在 m3u8 本身中看到的那样
#EXTM3U
# Created with Bento4 mp4-hls.py version 1.2.0r637

#EXT-X-VERSION:4

# Subtitles
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subtitles",NAME="English",LANGUAGE="en",URI="subtitles/en/subtitles.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subtitles",NAME="Español",LANGUAGE="es",URI="subtitles/es/subtitles.m3u8"

# Audio
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_aac",NAME="Français",LANGUAGE="fra",AUTOSELECT=YES,DEFAULT=YES,URI="audio/aac/fra/stream.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_aac",NAME="English",LANGUAGE="eng",AUTOSELECT=YES,URI="audio/aac/eng/stream.m3u8"

# Media Playlists
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2198120,BANDWIDTH=2416640,CODECS="avc1.4D401F,mp4a.40.2",RESOLUTION=1280x720,AUDIO="audio_aac",SUBTITLES="subtitles"
media-1/stream.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1001663,BANDWIDTH=1102896,CODECS="avc1.42C01E,mp4a.40.2",RESOLUTION=640x360,AUDIO="audio_aac",SUBTITLES="subtitles"
media-2/stream.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4007581,BANDWIDTH=4391894,CODECS="avc1.4D4029,mp4a.40.2",RESOLUTION=1920x1080,AUDIO="audio_aac",SUBTITLES="subtitles"
media-3/stream.m3u8
我认为这很容易:我添加了 -map 0:s:0获得第一个字幕,但 ffmpeg 告诉我没有这样命名的流。
然后我运行 ffprobe,它告诉我没有适合他的字幕流:
ffprobe "blahblah.m3u8" -show_streams -select_streams s
You can find here all the streams which the ffprobe command shows .有很多视频和音频流,但没有字幕流。
为什么 ffmpeg 和 ffprobe 找不到字幕流?是因为它们被拆分为不同的 m3u8 播放列表文件吗?

最佳答案

$sw = [Diagnostics.Stopwatch]::StartNew()
$files = Get-ChildItem ${Get-Location}
$loco = Get-Location
$p1 = Join-Path -Path $loco -ChildPath "/out"
New-Item -ItemType Directory -Force -Path $p1



function lnCodeTransform {
param( $String )
switch ($String)
{
"jpn" {"jp"}
"eng" {"en"}
"esp" {"es"}
"fra" {"fr"}
"deu" {"de"}
default {$String}
}
}


function lnNameTransform {
param( $String )
switch ($String)
{
"jpn" {"Japanese"}
"eng" {"English"}
"esp" {"Spanish"}
"fra" {"French"}
"deu" {"German"}
default {$String}
}
}


foreach ($f in $files){
if ($f.Name -eq "out"){
continue;
}
$p2 = Join-Path -Path $loco -ChildPath "/out/" | Join-Path -ChildPath $f
New-Item -ItemType Directory -Force -Path $p2/audio
New-Item -ItemType Directory -Force -Path $p2/video
New-Item -ItemType Directory -Force -Path $p2/subtitle
$sb = [System.Text.StringBuilder]::new();
[void]$sb.AppendLine( '#EXTM3U' )
[void]$sb.AppendLine( '#EXT-X-VERSION:3' )
#[void]$sb.AppendLine( '#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360' )
#[void]$sb.AppendLine( '360p.m3u8' )


New-Item -ItemType Directory -Force -Path $p2
$resStr = ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 $f.FullName;
$res = [convert]::ToInt32($resStr)
$audioTracks = ffprobe $f.FullName -show_entries stream=index:stream_tags=language,title -select_streams a -of compact=p=0:nk=1
$audioTracks = $audioTracks.split("\r")
foreach($audio in $audioTracks) {
$splited = $audio.split("|");
$ID = $splited[0]
$audioName = $splited[1];
$title = $splited[2];
ffmpeg -i $f.FullName -ss 0 -y -map 0:$ID -start_number 0 -acodec aac -b:a 320k -ac 2 -f segment -segment_time 10 -segment_list_size 0 -segment_list out/$f/audio/audio_"$ID.m3u8" -segment_format mpegts out/$f/audio/"audio_$ID""_%d.ts"
$name = lnNameTransform($audioName)
$code = lnCodeTransform($audioName)
[void]$sb.AppendLine( "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=`"aac`",LANGUAGE=`"$code`",NAME=`"$name ($title)`",DEFAULT=NO,AUTOSELECT=NO,URI=`"audio/audio_$ID.m3u8`"" )
}
$subTracks = ffprobe $f.FullName -show_entries stream=index:stream_tags=language,title -select_streams s -of compact=p=0:nk=1
$subTracks = $subTracks.split("\r")
foreach($subtitle in $subTracks) {
$splited = $subtitle.split("|");
$ID = $splited[0];
$subName = $splited[1];
$title = $splited[2];
ffmpeg -i $f.FullName -ss 0 -map 0:$ID -f segment -segment_time 10 -segment_list_size 0 -segment_list out/$f/subtitle/sub_"$ID.m3u8" -segment_format webvtt -scodec webvtt out/$f/subtitle/"sub_$ID%d.vtt"
$name = lnNameTransform($subName)
$code = lnCodeTransform($subName)
[void]$sb.AppendLine( "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=`"subs`",LANGUAGE=`"$code`",NAME=`"$name ($title)`",FORCED=NO,AUTOSELECT=NO,URI=`"subtitle/sub_$ID.m3u8`"" )
}

[void]$sb.AppendLine( '#EXT-X-STREAM-INF:BANDWIDTH=1400000,CODECS="avc1.4d4015,mp4a.40.2",RESOLUTION=842x480,AUDIO="aac",SUBTITLES="subs"' )
[void]$sb.AppendLine( 'video/480p.m3u8' )
#ffmpeg -i $f.FullName -c:a copy -vf scale=w=640:h=360:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -rc cqp -qp_p 0 -qp_i 1 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 800k -maxrate 856k -bufsize 1200k -b:a 96k -hls_segment_filename out/$f/360p_%03d.ts out/$f/360p.m3u8 -vf scale=w=842:h=480:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -gpu 1 -c:v h264_amf -rc cqp -qp_p 0 -qp_i 1 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 1400k -maxrate 1498k -bufsize 2100k -b:a 128k -hls_segment_filename out/$f/480p_%03d.ts out/$f/480p.m3u8 -vf scale=w=1280:h=720:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -gpu 1 -c:v h264_amf -rc cqp -qp_p 0 -qp_i 1 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 2800k -maxrate 2996k -bufsize 4200k -b:a 128k -hls_segment_filename out/$f/720p_%03d.ts out/$f/720p.m3u8 -vf scale=w=1920:h=1080:force_original_aspect_ratio=decrease -c:a aac -ar 48000 -gpu 1 -c:v h264_amf -rc cqp -qp_p 0 -qp_i 1 -profile:v main -crf 20 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 4 -hls_playlist_type vod -b:v 5000k -maxrate 5350k -bufsize 7500k -b:a 192k -hls_segment_filename out/$f/1080p_%03d.ts out/$f/1080p.m3u8
#ffmpeg -hwaccel auto -hwaccel_device 0 -i $f.FullName -c:v h264 -profile:v main -pix_fmt yuv420p -c:a aac -filter:v scale=360:640 -ar 48000 -rc cqp -qp_p 0 -qp_i 1 -profile:v main -crf 23 -sc_threshold 0 -g 48 -b:v 800k -maxrate 856k -bufsize 1200k -b:a 96k -keyint_min 4 -start_number 0 -hls_time 10 -hls_playlist_type vod -hls_list_size 0 -f hls -hls_segment_filename out/$f/360p_%03d.ts out/$f/360p.m3u8
#ffmpeg -hwaccel auto -hwaccel_device 0 -i $f.FullName -c:v h264 -profile:v main -pix_fmt yuv420p -c:a aac -filter:v scale=360:640 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/360p_%03d.ts out/$f/360p.m3u8
#ffmpeg -i $f.FullName -c:v h264 -crf 23 -b:v 1200k -minrate 500k -maxrate 2100k -profile:v main -pix_fmt yuv420p -y -filter:v scale=-2:480 -map 0:v -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/video/480p_%03d.ts out/$f/video/480p.m3u8
ffmpeg -i $f.FullName -c:v h264_qsv -preset slow -global_quality 30 -look_ahead 1 -profile:v main -level:v 4.1 -rc:v vbr_hq -rc-lookahead:v 32 -pix_fmt yuv420p -y -filter:v scale=-2:480 -map 0:v -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/video/480p_%03d.ts out/$f/video/480p.m3u8
If($res -ge 720) {
#ffmpeg -i $f.FullName -c:v h264_qsv -crf 23 -b:v 2400k -minrate 1200k -maxrate 4200k -profile:v main -pix_fmt yuv420p -filter:v scale=-2:720 -map 0:v -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/video/720p_%03d.ts out/$f/video/720p.m3u8
ffmpeg -i $f.FullName -c:v h264_qsv -preset slow -global_quality 28 -look_ahead 1 -profile:v main -level:v 4.1 -rc:v vbr_hq -rc-lookahead:v 32 -pix_fmt yuv420p -filter:v scale=-2:720 -map 0:v -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/video/720p_%03d.ts out/$f/video/720p.m3u8
[void]$sb.AppendLine( '#EXT-X-STREAM-INF:BANDWIDTH=2800000,CODECS="avc1.4d4015,mp4a.40.2",RESOLUTION=1280x720,AUDIO="aac",SUBTITLES="subs"' )
[void]$sb.AppendLine( 'video/720p.m3u8' )
}
If($res -ge 900) {
#ffmpeg -i $f.FullName -c:v h264 -crf 30 -b:v 4800k -minrate 2000k -maxrate 8400k -profile:v main -pix_fmt yuv420p -filter:v scale=-2:1080 -map 0:v -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/video/1080p_%03d.ts out/$f/video/1080p.m3u8
ffmpeg -i $f.FullName -c:v h264_qsv -preset slow -global_quality 26 -look_ahead 1 -profile:v main -level:v 4.1 -rc:v vbr_hq -rc-lookahead:v 32 -pix_fmt yuv420p -filter:v scale=-2:1080 -map 0:v -start_number 0 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename out/$f/video/1080p_%03d.ts out/$f/video/1080p.m3u8

[void]$sb.AppendLine( '#EXT-X-STREAM-INF:BANDWIDTH=5000000,CODECS="avc1.4d4015,mp4a.40.2",RESOLUTION=1920x1080,AUDIO="aac",SUBTITLES="subs"' )
[void]$sb.AppendLine( 'video/1080p.m3u8' )
}

$p3 = Join-Path -Path $p2 -ChildPath "/index.m3u8"
#echo $index | Out-File -Encoding UTF8 -LiteralPath $p3
echo $sb.ToString()
[System.IO.File]::WriteAllLines($p3, $sb.ToString().Trim().replace("`r`n", "`n"))
}
$sw.Stop()
echo $sw.Elapsed
这是我用来将文件转换为 HLS 并生成 index.m3u8 文件的脚本。是的,您需要编辑索引,但它会完成所有工作。此脚本也使用 Intel gpu。您可以删除 _qsv 以使其在任何 CPU 上工作

关于Ffmpeg 和 ffprobe 未在 m3u8 文件中显示字幕流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67482947/

25 4 0