iOS音频视频拼接,视频视频拼接

在一个unity3d项目中加录屏功能,录屏用的第三方ShareREC,由于是声控游戏,关闭了录屏功能的音频,单独录制了声控时候的声音,并且每局游戏的的视频前面加视频广告,这里就牵涉到录屏的视频要加上录声控时候的声音的拼接,及整改游戏视频拼接视频广告。写了个工具类FileTools,里面有对文件的各种操作

#import "FileTools.h"

@implementation FileTools

+(NSString*)tempDirectory

{

return  NSTemporaryDirectory();

}

+ (NSString *)cacheDirectory

{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

return [paths objectAtIndex:0];

}

+ (NSString *)documentDirectory

{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

return [paths objectAtIndex:0];

}

+ (NSString *)createDirectoryInDocumentDirectory:(NSString *)pathName

{

NSString *doc = [self documentDirectory];

NSFileManager *fileHandle = [NSFileManager defaultManager];

NSString *path = [doc stringByAppendingPathComponent:pathName];

if(![fileHandle fileExistsAtPath:path]) {

NSError *error;

if([fileHandle createDirectoryAtPath:path withIntermediateDirectories:false attributes:nil error:&error]) {

}

else {

return nil;

}

}else{//文件夹存在

NSError *error;

if( [fileHandle removeItemAtPath:path error:&error]){

if([fileHandle createDirectoryAtPath:path withIntermediateDirectories:false attributes:nil error:&error]) {

}

else {

return nil;

}

}

}

return path;

}

+ (NSString *)createFileInDocumentDirectory:(NSString *)fileName

{

NSString *doc = [self documentDirectory];

NSFileManager *fileHandle = [NSFileManager defaultManager];

NSString *path = [doc stringByAppendingPathComponent:fileName];

if(![fileHandle fileExistsAtPath:path]) {

if([fileHandle createFileAtPath:path contents:nil attributes:nil]) {

}

else {

return nil;

}

}

return path;

}

+ (BOOL)removeFileWithUrl:(NSURL*)fileUrl

{

NSFileManager *fileManager = [NSFileManager defaultManager];

if (fileUrl) {

if ( [fileManager removeItemAtURL:fileUrl error:NULL]) {

return YES;

}

}

return NO;

}

+ (BOOL)ModifyFileNameWithPath:(NSString*)filePath  toPath:(NSString*)toPath

{

NSFileManager *fm = [NSFileManager defaultManager];

NSError *error;

BOOL isSuccess;

isSuccess = [fm moveItemAtPath:filePath toPath:toPath error:&error];

return isSuccess;

}

@end

然后单独写了个视频声音管理的SoundRecord类,并且这是个单例

#import <ShareREC/ShareREC.h>

#import <ShareREC/Extension/ShareREC+Ext.h>

#import  <ShareREC/ShareREC.framework/Headers/Extension/ShareREC+RecordingManager.h>

#import <CoreGraphics/CoreGraphics.h>

#import <AssetsLibrary/ALAsset.h>

#import <AssetsLibrary/ALAssetsLibrary.h>

#import <AssetsLibrary/ALAssetsGroup.h>

#import <AssetsLibrary/ALAssetRepresentation.h>

#import "ShareRecUnity3DExtension.h"

#import "SoundRecord.h"

#import <AVFoundation/AVFoundation.h>

#import "FileTools.h"

#define  kAudioFileName @"sound.mp4"

#define kVideoWithSoundFileName @"VideoWithSoundFileName.mp4"

#define kGameName @"shengkongGame"

@interface SoundRecord()<AVAudioRecorderDelegate,UIAlertViewDelegate>

@property (nonatomic, strong)  AVAudioRecorder * recorder;

@property (nonatomic, strong) AVAudioSession *session;

@property (nonatomic,strong) NSTimer *soundTimer;//录音声波监控(注意这里暂时不对播放进行监控)

/** 合成视频文件 */

@property (nonatomic, strong) NSURL *outPutUrl;

@end

@implementation SoundRecord

static SoundRecord *_instance;

+ (id)allocWithZone:(NSZone *)zone

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instance = [super allocWithZone:zone];

});

return _instance;

}

+ (SoundRecord *)sharedInstance

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instance = [[self alloc] init];

});

return _instance;

}

- (instancetype)init

{

self = [super init];

if (self) {

self.mergeVideoStatus = 0;

}

return self;

}

- (void)prepareRecord

{

// 真机环境下需要的代码

_session = [AVAudioSession sharedInstance];

NSError *sessionError;

//既要播放声音又需要录音

//    [_session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];

//设置播放器为扬声器模式

//    [_session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];

[_session setCategory:AVAudioSessionCategoryPlayAndRecord

withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker

error:&sessionError];

if(_session == nil){

NSLog(@"Error creating session: %@", [sessionError description]);

}else{

//苹果推荐显示激活AVAudioSession

[_session setActive:YES error:nil];

}

// 1.获取沙盒地址

self.recordFileUrl = [NSURL fileURLWithPath:[FileTools createFileInDocumentDirectory:kAudioFileName]];

// 3.设置录音的一些参数

NSMutableDictionary *setting = [NSMutableDictionary dictionary];

// 音频格式

setting[AVFormatIDKey] = @(kAudioFormatMPEG4AAC);

// 录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量)

setting[AVSampleRateKey] = @(44100.0);

// 音频通道数 1 或 2

setting[AVNumberOfChannelsKey] = @(1);

// 线性音频的位深度  8、16、24、32

setting[AVLinearPCMBitDepthKey] = @(16);

//录音的质量

setting[AVEncoderAudioQualityKey] = [NSNumber numberWithInt:AVAudioQualityHigh];

//是否使用浮点数采样

setting[AVLinearPCMIsFloatKey] =  @(YES) ;

_recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:setting error:NULL];

_recorder.delegate = self;

[_recorder prepareToRecord];

_recorder.meteringEnabled = YES;

}

// 开始录音

- (void)startRecord

{

self.mergeVideoStatus = 0;

// 录音时停止播放 删除曾经生成的文件

[self prepareRecord];

[_recorder record];

[_recorder updateMeters];

_soundTimer = [NSTimer scheduledTimerWithTimeInterval:0.1

target:self

selector:@selector(audioPowerChange) userInfo:nil

repeats:YES];

}

/**

*  录音声波状态设置

*/

-(void)audioPowerChange{

[_recorder updateMeters];//更新测量值

CGFloat power= [_recorder averagePowerForChannel:0];//取得第一个通道的音频,注意音频强度范围时-160到0

//转换成0~160  (0是安静,160最大,当然是可以超过160的,超过极限大就超过160)

//    self.power = (power + 160);

//转换最高分贝值,范围是0到1。0最小,1最大。

self.power = pow(10, (0.05 * power));

NSLog(@"声音分贝 xxxxx == %f",self.power);

}

//结束录音

- (void)endRecored

{

[_recorder stop];

_recorder = nil;

if (_soundTimer) {

[_soundTimer invalidate];

_soundTimer = nil;

}

self.power = 0.0;

}

//合成新视频 用没有声音的MP4和录制的声音(返回新视频路径)

- (void)addSoundToVideo:(NSURL*)videoUrl

soundUrl:(NSURL*)soundUrl

completion:(void (^)(NSURL*newVideoUrl))handler

{

// 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.

AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];

AVAsset *videoAsset = [AVAsset assetWithURL:videoUrl];

// 2 - Video track

AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo

preferredTrackID:kCMPersistentTrackID_Invalid];

[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)

ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];

// 3 - Audio track 添加背景音乐的

AVURLAsset *audioAsset = [[AVURLAsset alloc] initWithURL:soundUrl options:nil];

AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio

preferredTrackID:kCMPersistentTrackID_Invalid];

[AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)

ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

NSString * tmpPath  = NSTemporaryDirectory();

NSString * filePath = [tmpPath stringByAppendingPathComponent:kVideoWithSoundFileName];

self.outPutUrl = [NSURL fileURLWithPath:filePath];

// 5 - Create exporter

AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition

presetName:AVAssetExportPresetHighestQuality];

exporter.outputURL = self.outPutUrl;

exporter.outputFileType = AVFileTypeQuickTimeMovie;

exporter.shouldOptimizeForNetworkUse = YES;

[exporter exportAsynchronouslyWithCompletionHandler:^{

//删除录音

[FileTools removeFileWithUrl:self.recordFileUrl];

//删除ShareREC录制的视频 (清除所有本地视频)

[ShareREC clearLocalRecordings];

[self exportDidFinish:self.outPutUrl];

//        if(handler){

//            handler(self.outPutUrl);

//        }

}];

}

- (void)exportDidFinish:(NSURL*)outputURL{

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {

[library writeVideoAtPathToSavedPhotosAlbum:outputURL completionBlock:^(NSURL *assetURL, NSError *error){

//删除合成的临时视频

[FileTools removeFileWithUrl:outputURL];

dispatch_async(dispatch_get_main_queue(), ^{

if (error) {

self.mergeVideoStatus = 2;

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"视频保存相册失败"

message:nil

delegate:self

cancelButtonTitle:@"重来一局"

otherButtonTitles:nil];

[alert show];

} else {

self.mergeVideoStatus = 1;

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"视频保存相册成功"

message:nil

delegate:self

cancelButtonTitle:@"重来一局"

otherButtonTitles:nil];

[alert show];

}

});

}];

}

}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

if (buttonIndex == 0) {

self.mergeVideoStatus = 3;//重新开始游戏

}

}

- (void)removeRecordSoundAndVideo

{

//删除录音

[FileTools removeFileWithUrl:self.recordFileUrl];

//删除ShareREC录制的视频 (清除所有本地视频)

[ShareREC clearLocalRecordings];

}

@end

好了在用的地方先是c方法,在c方法里面再调用声音控制单例完成

#import "ShareRecUnity3DExtension.h"

#import <ShareREC/ShareREC.h>

#import <ShareREC/Extension/ShareREC+Ext.h>

#import  <ShareREC/ShareREC.framework/Headers/Extension/ShareREC+RecordingManager.h>

#import "JSONKit.h"

#import "SoundRecord.h"

#if defined (__cplusplus)

extern "C" {

#endif

extern   float __iosXZdB();//小走分贝

extern   float __iosXZSpeed();//小走速度

extern   float __iosDZdB();//大走分贝

extern   float __iosDZSpeed();//大走速度

extern   float __iosXTdB();//小跳分贝

extern   float __iosXTGD();//小跳高度

extern   float __iosDTdB();//大跳分贝

extern   float __iosDTGD();//大跳高度

extern  float __iosGetRecordingdB();//获取当前声音分贝

extern  void __iosStartRecordSound();//开始录音

extern  void __iosEndRecordSound();//结束录音

extern  void __iosStartMergeVideos();//开始合并视频

extern  void __iosRemoveAudioAndVideo();//删除视频

extern  int __iosMergeVideosStatus();//返回视频合成状态(0正在合成,1合成成功,2合成失败)

/**

* @brief 初始化ShareRec

*

* @param appKey 应用Key

*/

extern void __iosShareRECRegisterApp(void *appKey);

/**

* @brief 开始录制

*/

extern void __iosShareRECStartRecording();

/**

* @brief 结束录制

*

@param  observer    观察回调对象名称

*/

extern void __iosShareRECStopRecording (void *observer);

/**

* @brief 播放最后一个录像

*/

extern void __iosShareRECPlayLastRecording ();

/**

* @brief 设置码率,默认为800kbps = 800 * 1024

*

* @param bitRate 码率

*/

extern void __iosShareRECSetBitRate (int bitRate);

/**

* @brief 设置帧率

*

* @param fps 帧率

*/

extern void __iosShareRECSetFPS (int fps);

/**

* @brief 设置最短录制时间,默认4秒

*

* @param time    时间,0表示不限制

*/

extern void __iosShareRECSetMinimumRecordingTime(float time);

/**

* @brief 获取最后一个录像的路径

*/

extern const char* __iosShareRECLastRecordingPath ();

/**

*  编辑最后一个录像

*

@param title    标题

@param userData 用户数据

@param observer 回调对象名称

*/

extern void __iosShareRECEditLastRecording (void *title, void *userData, void *observer);

/**

*  编辑最后一个录像

*

@param observer 回调对象名称

*/

extern void __iosShareRECEditLastRecordingNew (void *observer);

/**

*  设置是否同步录入语音解说

*

@param syncAudioComment 同步语音解说标识,YES 表示同步录入, NO 表示不录入。

*/

extern void __iosShareRECSetSyncAudioComment (bool syncAudioComment);

#if defined (__cplusplus)

}

#endif

#if defined (__cplusplus)

extern "C" {

#endif

extern void UnitySendMessage(const char* obj, const char* method, const char* msg);

float __iosXZdB(){//小走分贝

return 0.05;

}

float __iosXZSpeed()//小走速度

{

return 2;

}

float __iosDZdB()//大走分贝

{

return 0.15;

}

float __iosDZSpeed()//大走速度

{

return 3;

}

float __iosXTdB()//小跳分贝

{

return 0.2;

}

float __iosXTGD()//小跳高度

{

return 100;

}

float __iosDTdB()//大跳分贝

{

return 0.4;

}

float __iosDTGD()//大跳高度

{

return 200;

}

float __iosGetRecordingdB()

{

return   [SoundRecord sharedInstance].power;

}

void __iosStartRecordSound()

{

[[SoundRecord sharedInstance] startRecord];

}

void __iosEndRecordSound()

{

[[SoundRecord sharedInstance] endRecored];

}

void __iosRemoveAudioAndVideo()

{

[[SoundRecord sharedInstance] removeRecordSoundAndVideo];

}

int  __iosMergeVideosStatus()

{

return  [SoundRecord sharedInstance].mergeVideoStatus;

}

void __iosStartMergeVideos()

{

NSURL *gameSoundUrl = [SoundRecord sharedInstance].recordFileUrl;

//               SRERecording * recording =  [[ShareREC  currentLocalRecordings] lastObject];

[[SoundRecord sharedInstance] addSoundToVideo:[NSURL fileURLWithPath: [ShareREC lastRecordingPath]]

soundUrl:gameSoundUrl

completion:nil

];

}

void __iosShareRECRegisterApp(void *appKey)

{

NSString *appKeyStr = nil;

if (appKey)

{

appKeyStr = [NSString stringWithCString:appKey encoding:NSUTF8StringEncoding];

}

[ShareREC registerApp:appKeyStr];

}

void __iosShareRECStartRecording()

{

[ShareREC startRecording];

}

void __iosShareRECStopRecording (void *observer)

{

NSString *observerStr = nil;

if (observer)

{

observerStr = [NSString stringWithCString:observer encoding:NSUTF8StringEncoding];

}

[ShareREC stopRecording:^(NSError *error) {

NSMutableDictionary *resultDict = [NSMutableDictionary dictionaryWithDictionary:@{@"name" : @"StopRecordingFinished"}];

if (error)

{

NSDictionary *errDict = @{@"code" : @(error.code), @"message" : error.localizedDescription ? error.localizedDescription : @""};

[resultDict setObject:errDict forKey:@"error"];

}

NSString *resultStr = [resultDict JSONString];

UnitySendMessage([observerStr UTF8String], "shareRECCallback", [resultStr UTF8String]);

}];

}

void __iosShareRECPlayLastRecording ()

{

[ShareREC playLastRecording];

}

void __iosShareRECSetBitRate (int bitRate)

{

[ShareREC setBitRate:bitRate];

}

void __iosShareRECSetFPS (int fps)

{

[ShareREC setFPS:fps];

}

void __iosShareRECSetMinimumRecordingTime(float time)

{

[ShareREC setMinimumRecordingTime:time];

}

const char* __iosShareRECLastRecordingPath ()

{

if ([ShareREC lastRecordingPath])

{

return strdup([[ShareREC lastRecordingPath] UTF8String]);

}

return strdup([@"" UTF8String]);

}

void __iosShareRECEditLastRecording (void *title, void *userData, void *observer)

{

NSString *titleStr = nil;

if (title)

{

titleStr = [NSString stringWithCString:title encoding:NSUTF8StringEncoding];

}

NSDictionary *userDataDict = nil;

if (userData)

{

NSString *userDataStr = [NSString stringWithCString:userData encoding:NSUTF8StringEncoding];

userDataDict = [userDataStr objectFromJSONString];

}

NSString *observerStr = nil;

if (observer)

{

observerStr = [NSString stringWithCString:observer encoding:NSUTF8StringEncoding];

}

[ShareREC editLastRecordingWithTitle:titleStr userData:userDataDict onClose:^{

NSDictionary *resultDict = @{@"name" : @"SocialClose"};

NSString *resultStr = [resultDict JSONString];

UnitySendMessage([observerStr UTF8String], "shareRECCallback", [resultStr UTF8String]);

}];

}

void __iosShareRECEditLastRecordingNew (void *observer)

{

NSString *observerStr = nil;

if (observer)

{

observerStr = [NSString stringWithCString:observer encoding:NSUTF8StringEncoding];

}

[ShareREC editLastRecording:^(BOOL cancelled) {

NSDictionary *resultDict = @{@"name" : @"EditResult", @"cancelled" : @(cancelled)};

NSString *resultStr = [resultDict JSONString];

UnitySendMessage([observerStr UTF8String], "shareRECCallback", [resultStr UTF8String]);

}];

}

void __iosShareRECSetSyncAudioComment (bool syncAudioComment)

{

[ShareREC setSyncAudioComment:syncAudioComment ? YES : NO];

}

#if defined (__cplusplus)

}

#endif

@implementation ShareRecUnity3DExtension

@end

原文地址:https://www.cnblogs.com/yeas/p/10490838.html

时间: 2024-08-07 03:54:52

iOS音频视频拼接,视频视频拼接的相关文章

iOS 音频视频制作

--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音效 音乐 音频会话 录音 音频队列服务 视频 MPMoviePlayerController MPMoviePlayerViewController AVPlayer 摄像头 UIImagePicker

iOS音频播放、录音、视频播放、拍照、视频录制

随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音效 音乐 音频会话 录音 音频队列服务 视频 MPMoviePlayerController MPMoviePlayerViewController AVPlayer 摄像头 UIImagePickerController拍照

iOS音频视频开发起始点

Audio & Video Starting Point Multimedia technologies in iOS let you access the sophisticated audio and video capabilities of iPhone, iPad, and iPod touch. Specialized classes let you easily add basic features such as iPod library playback and movie c

iOS平台上的音视频即时通讯应用开发

现在IOS很是火热,一大堆开发人员在捣鼓IOS平台的开发,相信大家也使用过QQ的语音视频对话功能,但是不知道大家有没有试过自己来开发一个基于IOS平台的音视频即时通讯的应用,这个应用必须能够做到跨平台 支持iOS平台设备上的音频即时通讯应用开发 提供Objective-C语言API接口,开放示例源代码 集成H.264.AAC.AMR等编解码技术 封装音视频的采集.编解码.传输.显示和播放等模块 支持Android.Web.PC等设备和iOS之间的互联互通 想要在IOS平台下实现音视频通信,最快捷

ios设备突破微信小视频6S限制的方法

刷微信朋友圈只发文字和图片怎能意犹未竟,微信小视频是一个很好的补充,音视频到位,流行流行最流行.但小视频时长不能超过6S,没有滤镜等是很大的遗憾.but有人突破限制玩出了花样,用ios设备在朋友圈晒出超时长.带滤镜甚至慢镜头拍摄的小视频.随ytkah一起看看他们是怎么玩的吧 未越狱ios设备在微信朋友圈上传延时.慢动作.滤镜.超时长小视频的方法: 第①步,将iPhone拍摄好的延时.超时长或者慢动作的视频保存到本地电脑,并同时截取一张视频画面保存.(PS:添加滤镜效果可以通过iMovie等App

照相、从相册上取照片、播放音频、播放本地视频、播放网络视频、MPMoviePlayerController

一.照相.从相册上去照片 1. 先判断是否支持照相功能 *判断当前设备是否支持照相功能,支持返回YES 否则返回NO 注意:模拟器不支持照相功能 把握一个原则只要是物理硬件相关的功能模拟器都不支持 例如: UIImagePickerController 专门处理与照片相关的功能类 是一个控制器 继承于导航视图控制器 if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]

android平台短视频技术之 视频编辑的经验分享.

提示一: 各位看官,这里分享的是视频编辑,即剪切/拼接/分离/合并/涂鸦/标记/叠加/滤镜等对视频的编辑操作.不是流媒体网络播放等功能,请注意. 提示二: 这些文字90%的为普及知识,10%为宣传我们的SDK,因为分享别人,有利自已,才是良性循环,才可以让我们持续分享,毕竟只分享,不有益很难持续下去.要养家糊口啊^_^. 提示三:我们是android视频编辑的专业团队,以下分享的文字,完全实际经验总结,每一个知识点您都可以在我们的SDK或开源的工程中验证.我们的SDK:https://githu

【转】直播流程,视频推流,视频拉流,简介,SMTP、RTMP、HLS、 PLPlayerKit

原:https://www.cnblogs.com/baitongtong/p/11248966.html 1 .音视频处理的一般流程: 数据采集→数据编码→数据传输(流媒体服务器) →解码数据→播放显示1.数据采集:摄像机及拾音器收集视频及音频数据,此时得到的为原始数据涉及技术或协议:摄像机:CCD.CMOS拾音器:声电转换装置(咪头).音频放大电路2.数据编码:使用相关硬件或软件对音视频原始数据进行编码处理(数字化)及加工(如音视频混合.打包封装等),得到可用的音视频数据涉及技术或协议:编码

手动抓取爱奇艺和优酷等视频网站的视频

今天就给大家讲讲怎么手动抓取爱奇艺和优酷等视频网站的视频该方法适用于很多视频网站.因为有的网站不支持我们用一些软件比如硕鼠和维棠等的解析下载,所以我就找到了这个方法,本来优酷之前是可以的,不过现在优酷还是不支持硕鼠和维棠的解析了.这两个网页是原帖的地址,其实我之前知道这个方法,不过这个人提供了一个软件比较好用,我把他录制的视频提取出来了,下面看看吧. 其实原理都是一样,这些视频网站为了让视频更快的缓存,当然也有很多其他原因,把视频分成了很多段,所以我们只需要单独下载好每一段视频,然后把这些视频合