#cocoa #qtkit #live-streaming
#cocoa #qtkit #прямая трансляция
Вопрос:
Я пытаюсь создать приложение для Mac, которое создавало бы потоковое видео в реальном времени. Я знаю о VLC и других решениях, но все же.
С этой целью я пытаюсь записывать видео из iSight с помощью QTKit и сохранять его непрерывно в виде серии крошечных видеофайлов. Однако запись получается не совсем непрерывной, с промежутками между файлами.
По сути, я просто настраиваю таймер, который начинает запись в новый файл через определенные промежутки времени, тем самым останавливая старую запись. Я также попытался установить максимальную записанную длину и использовать метод делегирования … didFinishRecording … и …Завершит запись …, но с тем же результатом (я не могу оценить разницу между пробелами в этих случаях).
Пожалуйста, помогите мне, если вы знаете, как это должно быть сделано.
Вот мой текущий код:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
QTCaptureSession *session = [[QTCaptureSession alloc] init];
QTCaptureDevice *iSight = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
[iSight open:nil];
QTCaptureDeviceInput *myInput = [QTCaptureDeviceInput deviceInputWithDevice:iSight];
output = [[QTCaptureMovieFileOutput alloc] init] ; //ivar, QTCaptureFileOutput
[output setDelegate:self];
a = 0; //ivar, int
fileName = @"/Users/dtv/filerecording_"; //ivar, NSString
[session addOutput:output error:nil];
[session addInput:myInput error:nil];
[capview setCaptureSession:session]; //IBOutlet
[session startRunning];
[output setCompressionOptions:[QTCompressionOptions compressionOptionsWithIdentifier:@"QTCompressionOptionsSD480SizeH264Video"] forConnection:[[output connections] objectAtIndex:0]];
[output recordToOutputFileURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%i.mov", fileName, a]] bufferDestination:QTCaptureFileOutputBufferDestinationOldFile];
NSTimer *tmr = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(getMovieLength:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:tmr forMode:NSDefaultRunLoopMode];
}
‐ (void) getMovieLength:(NSTimer *) t {
a ;
[output recordToOutputFileURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%i.mov", fileName, a]] bufferDestination:QTCaptureFileOutputBufferDestinationOldFile];
}
Ответ №1:
Существует встроенный механизм для разбиения захваченного фильма на части. Используйте
[QTCaptureFileOutput setMaximumRecordedDuration:]
чтобы указать продолжительность фрагмента или
[QTCaptureFileOutput setMaximumRecordedFileSize:]
чтобы указать ограничение на размер файла.
При достижении предела будет вызван метод делегирования:
[QTCaptureFileOutput_Delegate captureOutput: shouldChangeOutputFileAtURL: forConnections: dueToError:]
В этом методе вы можете задать новое имя файла:
[QTCaptureFileOutput recordToOutputFileURL:]
Это позволит вам довольно точно вырезать фрагменты записанного фильма.
Обратите внимание, что [QTCaptureFileOutput_Delegate captureOutput: didFinishRecordingToOutputFileAtURL: forConnections: dueToError:] будет вызван немного позже после фактического завершения перекодирования в файл. Если вы используете этот метод для установки нового файла, в конечном видео будут пробелы. Это не значит, что вам не нужно использовать этот метод. Этот метод будет указан, когда фрагмент фильма будет готов к использованию.
Если вам нужна еще более точная нарезка, вы можете использовать
[QTCaptureFileOutput captureOutput: didOutputSampleBuffer: fromConnection:]
чтобы указать точный кадр фильма, когда начинать запись в новый фрагмент. Однако для работы с этим методом вам понадобятся более конкретные знания.
Комментарии:
1. Спасибо. К сожалению, пока не могу это проверить. Будет принято, как только я смогу это проверить.
2. Спасибо. Он работает намного плавнее, чем раньше. Но все же не совсем гладко. Что это за "более конкретные знания", о которых вы упомянули? Не могли бы вы сказать мне, где я могу его найти? С наилучшими пожеланиями, Тимофей.
3. Что значит не совсем гладко? Это должно работать очень хорошо. Когда я сказал, что вам нужны более конкретные знания, я просто не знал, насколько глубоко вам нужно копаться в материалах QuickTime. В большинстве случаев описанного мной метода достаточно, чтобы разбить захваченный фильм на части. Однако, если вам нужна более точная нарезка до одного кадра, вы можете использовать
[QTCaptureFileOutput captureOutput: didOutputSampleBuffer: fromConnection:]
метод. В этом случае вам нужно получить данные из буфера и проанализировать их. Ничего особенного, вы можете получить почти все из документации.4. Я имел в виду, что когда я просматриваю их все один за другим в VLC (и я воспроизводю их в правильном порядке), вы можете определить, где заканчивается один файл и начинается следующий. Хотя, я согласен, это может быть связано с тем, как работает VLC, поэтому я попытаюсь просмотреть это, скажем, в iMovie.
5. Это еще одна проблема. Новый фильм не может быть воспроизведен немедленно, требуется некоторое время для декодирования кадров. Для плавного воспроизведения фрагментов вам нужно добавить их один за другим в новый файл QTMovie с помощью метода [QTMovie appendSelectionFromMovie:] и воспроизвести этот фильм. В этом случае не будет разрыва, потому что фильм будет декодировать кадры заранее. Не беспокойтесь о размере, фактические данные не будут скопированы, а будут ссылаться. Если вы сохраните этот фильм на диск, вы увидите, что файл фильма маленький, если, конечно, вы не используете атрибут QTMovieFlatten.