簡體   English   中英

如何使用 ffmpeg-python 從視頻中獲取第一個音頻通道?

[英]How to get the first audio channel from a video with ffmpeg-python?

我想使用 ffmpeg-python 從視頻中獲取第一個音頻通道。

我試過這個:

  out, _ = (
        ffmpeg
            .input(filename)
            .output('pipe:', loglevel=0, format='s16le', acodec='pcm_s16le', ac=1, ar='8k')
            .run(capture_stdout=True)
    )
    """ extract audio signal """
    self.signal = (
        np
            .frombuffer(out, np.int16)  
    )

但我不確定這是否正確。

我在這里看了一下,但找不到解決方案: https ://trac.ffmpeg.org/wiki/AudioChannelManipulation

有什么建議嗎? 謝謝!

編輯:

我嘗試了@rotem 解決方案,它似乎有效。 但是,我還有另一個似乎與 -ac 標志有關的問題。 對於某些視頻,numpy 輸出具有正確的長度(即,它與原始音頻長度匹配)。 對於其他人,我弄錯了。 但是,如果我將這些視頻的 -ac 設置為 2,我會得到正確的信號長度。 你知道為什么會這樣嗎?

這是視頻的元數據(持續時間:2 分 11 秒),它輸出正確的 numpy 數組大小,並將 -ac 設置為 2

{'streams': [{'index': 0, 'codec_name': 'h264', 'codec_long_name': 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10', 'profile': 'High ','codec_type':'video','codec_tag_string':'avc1','codec_tag':'0x31637661','width':1920,'height':1080,'coded_width':1920,'coded_height':1080, 'closed_captions':0,'film_grain':0,'has_b_frames':0,'pix_fmt':'yuv420p','level':40,'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 ','id':'0x1','r_frame_rate':'30/1','avg_frame_rate':'176805000/5894849','time_base':'1/90000','start_pts':0,'start_time': '0.000000','duration_ts':11789698,'duration':'130.996644','bit_rate':'16999840','bits_per_raw_sample':'8','nb_frames':'3929','extradata_size':34,'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,'captions':0,'descriptions':0,'metadata':0,'dependent': 0, 'still_image': 0}, 'tags': {'creation_time': '2022-05-30T15:00:39.000000Z', 'language': 'eng', 'handler_name': 'VideoHandle', 'vendor_id' : '[0][0][0][0]'}}, {'index': 1, 'codec_name': 'aac', 'codec_long_name': 'AAC(高級音頻編碼)', 'profile': 'LC','codec_type':'audio','codec_tag_string':'mp4a','codec_tag':'0x6134706d','sample_fmt':'fltp','sample_rate':'48000','channels':2, 'channel_layout':'stereo','bits_per_sample':0,'id':'0x2','r_frame_rate':'0/0','avg_frame_rate':'0/0','time_base':'1/48000 ','start_pts':696,'start_time':'0.014500','duration_ts':6285214,'duration':'130.941958','bit_rate':'256004','nb_frames':'6138','extradata_size': 2、'disposition': {'default': 1, 'dub': 0, 'original': 0, 'comment': 0, 'lyrics': 0, 'karaoke': 0, 'forced': 0, '聽力受損':0,'視覺受損':0,' clean_effects': 0, 'attached_pic': 0, 'timed_thumbnails': 0, 'captions': 0, 'descriptions': 0, 'metadata': 0, 'dependent': 0, 'still_image': 0}, 'tags ':{'creation_time':'2022-05-30T15:00:39.000000Z','語言':'eng','handler_name':'SoundHandle','vendor_id':'[0][0][0] [0]'}}], '格式': {'filename': 'videos4/test_01.mp4', 'nb_streams': 2, 'nb_programs': 0, 'format_name': 'mov,mp4,m4a,3gp, 3g2,mj2','format_long_name':'QuickTime / MOV','start_time':'0.000000','duration':'130.996600','size':'282621379','bit_rate':'17259768','probe_score' :100,'標簽':{'major_brand':'mp42','minor_version':'0','compatible_brands':'isommp42','creation_time':'2022-05-30T15:00:39.000000Z',' com.android.version':'12','com.android.capture.fps':'30.000000'}}}。

相反,視頻的元數據(持續時間 5 分鍾)通過將 -ac 設置為 1 給出了正確的結果長度:

{'streams': [{'index': 0, 'codec_name': 'h264', 'codec_long_name': 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10', 'profile': 'High ','codec_type':'video','codec_tag_string':'avc1','codec_tag':'0x31637661','width':1920,'height':1080,'coded_width':1920,'coded_height':1080, 'closed_captions':0,'film_grain':0,'has_b_frames':0,'sample_aspect_ratio':'1:1','display_aspect_ratio':'16:9','pix_fmt':'yuv420p','level': 40,'field_order':'progressive','refs':1,'is_avc':'true','nal_length_size':'4','id':'0x1','r_frame_rate':'30/1', 'avg_frame_rate':'33862500/1128779','time_base':'1/90000','start_pts':0,'start_time':'0.000000','duration_ts':27090696,'duration':'301.007733','bit_rate ':'16999542','bits_per_raw_sample':'8','nb_frames':'9030','extradata_size':26,'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, 'captions': 0, 'descriptions': 0, 'metadata': 0, 'dependent': 0, 'still_image': 0}, 'tags': {'language': 'und', 'handler_name': 'VideoHandler', 'vendor_id': '[0][0][0][0]'}, 'side_data_list': [{'side_data_type': '顯示矩陣', 'displaymatrix': '\n00000000 : 0 65536 0\n00000001: -65536 0 0\n00000002: 0 0 1073741824\n', '旋轉': -90}]}, {'index': 1, 'codec_name': 'aac', 'codec_long_name': 'AAC(高級音頻編碼)','profile':'LC','codec_type':'audio','codec_tag_string':'mp4a','codec_tag':'0x6134706d','sample_fmt':'fltp',' sample_rate':'48000','channels':2,'channel_layout':'stereo','bits_per_sample':0,'id':'0x2','r_frame_rate':'0/0','avg_frame_rate':' 0/0','time_base':'1/48000','start_pts':0,'start_time':'0.000000','duration_ts':14448640,'duration':'301.013333','bit_rate':'256000' , 'nb_frames': '14110', 'extradata_size': 2, 'disposition': {'default': 1, 'dub': 0, 'original': 0, 'comment': 0, 'lyrics': 0, '卡拉 OK': 0, '強制 ed':0,'hearing_impaired':0,'visual_impaired':0,'clean_effects':0,'attached_pic':0,'timed_thumbnails':0,'captions':0,'descriptions':0,'metadata' : 0, '依賴': 0, 'still_image': 0}, 'tags': {'language': 'und', 'handler_name': 'SoundHandler', 'vendor_id': '[0][0][0 ][0]'}}], 'format': {'filename': 'videos4/video_02.mp4', 'nb_streams': 2, 'nb_programs': 0, 'format_name': 'mov,mp4,m4a,3gp ,3g2,mj2', 'format_long_name': 'QuickTime / MOV', 'start_time': '0.000000', 'duration': '301.014000', 'size': '649577064', 'bit_rate': '17263703', 'probe_score ':100,'標簽':{'major_brand':'isom','minor_version':'512','compatible_brands':'isomiso2avc1mp41','編碼器':'Lavf58.27.103'}}}

使用-map_channel輸出選項

-map_channel [input_file_id.stream_specifier.channel_id|-1][?][:output_file_id.stream_specifier]

(在上面鏈接的文檔中搜索“-map_channel”以獲取更多詳細信息。)

要僅映射第一個文件的第一個音頻流的第一個通道,請嘗試

ffmpeg -i INPUT -map_channel 0.0.0 OUTPUT

我能找到的最安全的解決方案是使用通道分割過濾器。

FFmpeg CLI 命令示例:
ffmpeg -y -vn -i stereo.mp4 -filter_complex "[0:a:0]channelsplit=channel_layout=mono:channels=FC[C0]" -map "[C0]" -acodec pcm_s16le -ac 1 -ar 8k first_channel.wav

優點是即使有視頻通道並且有多個音頻流,該命令也可以工作。


使用 FFmpeg CLI 創建用於測試的合成輸入文件(帶有音頻和視頻):

使用立體聲音頻構建示例:

ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1 -f lavfi -i sine=frequency=100 -f lavfi -i sine=frequency=1000 -map_channel 1.0.0 -map_channel 2.0.0 -acodec aac -ar 44100 -ac 2 -t 10 stereo.mp4

使用 6 通道音頻構建示例:

ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1 -f lavfi -i sine=frequency=100 -f lavfi -i sine=frequency=500 -f lavfi -i sine=frequency=600 -f lavfi -i sine=frequency=700 -f lavfi -i sine=frequency=800 -f lavfi -i sine=frequency=900 -map_channel 1.0.0 -map_channel 2.0.0 -map_channel 3.0.0 -map_channel 4.0.0 -map_channel 5.0.0 -map_channel 6.0.0 -acodec aac -ar 44100 -ac 6 -t 10 six_channels.mp4


用於獲取第一個音頻通道的 FFmpeg CLI 命令(用於測試):

ffmpeg -y -vn -i stereo.mp4 -filter_complex "[0:a:0]channelsplit=channel_layout=mono:channels=FC[C0]" -map "[C0]" -acodec pcm_s16le -ac 1 -ar 8k first_channel.wav

  • [0:a:0]獲取第一個輸入文件的第一個音頻流。
  • channelsplit=channel_layout=mono:channels=FC[C0]拆分音頻通道,獲取第一個音頻通道,並給它一個臨時名稱[C0]
  • -map "[C0]"將音頻通道映射到輸出。

使用 ffmpeg-python 的相同命令:

# audio_ch0 = ffmpeg.input(filename).audio.filter('channelsplit', channel_layout='mono', channels='FC')  # Does not handle the case of multiple audio streams.

# Using ['a:0'].filter instead of .audio.filter gets the first audio stream in case there are more than one.
audio_ch0 = ffmpeg.input(filename)['a:0'].filter('channelsplit', channel_layout='mono', channels='FC')

ffmpeg.output(audio_ch0, 'first_channel.wav', acodec='pcm_s16le', ac='1', ar='8k').global_args('-hide_banner', '-report').overwrite_output().run()

創建的日志文件顯示 FFmpeg 命令為:
ffmpeg -i stereo.mp4 -filter_complex "[0:a:0]channelsplit=channel_layout=mono:channels=FC[s0]" -map "[s0]" -ac 1 -acodec pcm_s16le -ar 8k first_channel.wav -hide_banner -report -y


測試:
通過聽力我們可以驗證first_channel.wav是第一個音頻通道(100Hz 正弦波)。
使用stereo.mp4six_channels.mp4進行測試。


對您的實施的調整:

import ffmpeg
import numpy as np

filename = 'stereo.mp4'

out, _ = (
    ffmpeg
    .input(filename)['a:0'].filter('channelsplit', channel_layout='mono', channels='FC')
    .output('pipe:', loglevel=0, format='s16le', acodec='pcm_s16le', ac=1, ar='8k')
    .run(capture_stdout=True)
)

""" extract audio signal """
self.signal = np.frombuffer(out, np.int16)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM