QTKit, захват видео для прямой трансляции

#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.