文档章节

iOS 三种录制视频方式

天机
 天机
发布于 2016/05/23 08:21
字数 3853
阅读 54
收藏 2
点赞 2
评论 0

UIImagePickerController

目前,将视频捕获集成到你的应用中的最简单的方法是使用 UIImagePickerController。这是一个封装了完整视频捕获管线和相机 UI 的 view controller。

在实例化相机之前,首先要检查设备是否支持相机录制:

1

2

3

4

5

6

7

8

if ([UIImagePickerController

       isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

    NSArray *availableMediaTypes = [UIImagePickerController

      availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];

    if ([availableMediaTypes containsObject:(NSString *)kUTTypeMovie]) {

        // 支持视频录制

    }

}

然后创建一个 UIImagePickerController 对象,设置好代理便于进一步处理录制好的视频 (比如存到相册) 以及对于用户关闭相机作出响应:

1

2

3

4

UIImagePickerController *camera = [UIImagePickerController new];

camera.sourceType = UIImagePickerControllerSourceTypeCamera;

camera.mediaTypes = @[(NSString *)kUTTypeMovie];

camera.delegate = self;

这是你实现一个功能完善的摄像机所需要写的所有代码。

相机配置

UIImagePickerController 提供了额外的配置选项。

通过设置 cameraDevice 属性可以选择一个特定的相机。这是一个 UIImagePickerControllerCameraDevice 枚举,默认情况下是 UIImagePickerControllerCameraDeviceRear,你也可以把它设置为 UIImagePickerControllerCameraDeviceFront。每次都应事先确认你想要设置的相机是可用的:

1

2

3

4

UIImagePickerController *camera = …

if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]) {

    [camera setCameraDevice:UIImagePickerControllerCameraDeviceFront];

}

videoQuality 属性用于控制录制视频的质量。它允许你设置一个特定的编码预设,从而改变视频的比特率和分辨率。以下是六种预设:

1

2

3

4

5

6

7

8

9

enum {

   UIImagePickerControllerQualityTypeHigh = 0,

   UIImagePickerControllerQualityTypeMedium = 1, // default value

   UIImagePickerControllerQualityTypeLow = 2,

   UIImagePickerControllerQualityType640x480 = 3,

   UIImagePickerControllerQualityTypeIFrame1280x720 = 4,

   UIImagePickerControllerQualityTypeIFrame960x540 = 5

};

typedef NSUInteger  UIImagePickerControllerQualityType;

前三种为相对预设 (low, medium, high)。这些预设的编码配置会因设备不同而不同。如果选择 high,那么你选定的相机会提供给你该设备所能支持的最高画质。后面三种是特定分辨率的预设 (640×480 VGA, 960×540 iFrame, 和 1280×720 iFrame)。

自定义 UI

就像上面提到的,UIImagePickerController 自带一套相机 UI,可以直接使用。然而,你也可以自定义相机的控件,通过隐藏默认控件,然后创建带有控件的自定义视图,并覆盖在相机预览图层上面:

1

2

3

UIView *cameraOverlay = …

picker.showsCameraControls = NO;

picker.cameraOverlayView = cameraOverlay;

然后你需要将你覆盖层上的控件关联上 UIImagePickerController 的控制方法 (比如,startVideoCapture 和 stopVideoCapture)。

AVFoundation

如果你想要更多关于处理捕获视频的方法,而这些方法是 UIImagePickerController 所不能提供的,那么你需要使用 AVFoundation。

AVFoundation 中关于视频捕获的主要的类是 AVCaptureSession。它负责调配影音输入与输出之间的数据流:

AVCaptureSession setup

使用一个 capture session,你需要先实例化,添加输入与输出,接着启动从输入到输出之间的数据流:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

AVCaptureSession *captureSession = [AVCaptureSession new];

AVCaptureDeviceInput *cameraDeviceInput = …

AVCaptureDeviceInput *micDeviceInput = …

AVCaptureMovieFileOutput *movieFileOutput = …

if ([captureSession canAddInput:cameraDeviceInput]) {

    [captureSession addInput:cameraDeviceInput];

}

if ([captureSession canAddInput:micDeviceInput]) {

    [captureSession addInput:micDeviceInput];

}

if ([captureSession canAddOutput:movieFileOutput]) {

    [captureSession addOutput:movieFileOutput];

}

[captureSession startRunning];

(为了简单起见,调度队列 (dispatch queue) 的相关代码已经从上面那段代码中省略了。所有对 capture session 的调用都是阻塞的,因此建议将它们分配到后台串行队列中。)

capture session 可以通过一个 sessionPreset

来进一步配置,这可以用来指定输出质量的等级。有 11 种不同的预设模式:

1

2

3

4

5

6

7

8

9

10

11

NSString *const  AVCaptureSessionPresetPhoto;

NSString *const  AVCaptureSessionPresetHigh;

NSString *const  AVCaptureSessionPresetMedium;

NSString *const  AVCaptureSessionPresetLow;

NSString *const  AVCaptureSessionPreset352x288;

NSString *const  AVCaptureSessionPreset640x480;

NSString *const  AVCaptureSessionPreset1280x720;

NSString *const  AVCaptureSessionPreset1920x1080;

NSString *const  AVCaptureSessionPresetiFrame960x540;

NSString *const  AVCaptureSessionPresetiFrame1280x720;

NSString *const  AVCaptureSessionPresetInputPriority;

第一个代表高像素图片输出。 接下来的九个和之前我们在设置 UIImagePickerController 的 videoQuality 时看到过的 UIImagePickerControllerQualityType 选项非常相似,不同的是,这里有一些额外可用于 capture session 的预设。 最后一个 (AVCaptureSessionPresetInputPriority) 代表 capture session 不去控制音频与视频输出设置。而是通过已连接的捕获设备的 activeFormat 来反过来控制 capture session 的输出质量等级。在下一节,我们将会看到更多关于设备和设备格式的细节。

  • 输入

AVCaptureSession 的输入其实就是一个或多个的 AVCaptureDevice 对象,这些对象通过 AVCaptureDeviceInput 连接上 capture session。

我们可以使用 [AVCaptureDevice devices] 来寻找可用的捕获设备。以 iPhone 6 为例:

1

2

3

4

5

(

    “<avcapturefigvideodevice: 0x136514db0 [back camera][com.apple.avfoundation.avcapturedevice.built-in_video:0]>”,

    “<avcapturefigvideodevice: 0x13660be80 [front camera][com.apple.avfoundation.avcapturedevice.built-in_video:1]>”,

    “<avcapturefigaudiodevice: 0x174265e80 [iphone microphone][com.apple.avfoundation.avcapturedevice.built-in_audio:0]>”

)</avcapturefigaudiodevice: 0x174265e80 [iphone microphone][com.apple.avfoundation.avcapturedevice.built-in_audio:0]></avcapturefigvideodevice: 0x13660be80 [front camera][com.apple.avfoundation.avcapturedevice.built-in_video:1]></avcapturefigvideodevice: 0x136514db0 [back camera][com.apple.avfoundation.avcapturedevice.built-in_video:0]>

  • 视频输入

配置相机输入,需要实例化一个 AVCaptureDeviceInput 对象,参数是你期望的相机设备,然后把它添加到 capture session:

1

2

3

4

5

6

7

AVCaptureSession *captureSession = …

AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

NSError *error;

AVCaptureDeviceInput *cameraDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:cameraDevice error:&error];

if ([captureSession canAddInput:input]) {

    [captureSession addInput:cameraDeviceInput];

}

如果上面提到的 capture session 预设列表里能满足你的需求,那你就不需要做更多的事情了。如果不够,比如你想要高的帧率,你将需要配置具体的设备格式。一个视频捕获设备有许多设备格式,每个都带有特定的属性和功能。下面是对于 iPhone6 的后置摄像头的一些例子 (一共有 22 种可用格式):

baioge600.jpg

  • 格式 = 像素格式

  • FPS = 支持帧数范围

  • HRSI = 高像素静态图片尺寸

  • FOV = 视角

  • VIS = 该格式支持视频防抖

  • Upscales = 加入数字 upscaling 时的放大比例

  • AF = 自动对焦系统(1 是反差对焦,2 是相位对焦)

  • ISO = 支持感光度范围

  • SS = 支持曝光时间范围

  • HDR = 支持高动态范围图像

通过上面的那些格式,你会发现如果要录制 240 帧每秒的视频的话,可以根据想要的像素格式选用第一个或第二个格式。另外若是要捕获 1920×1080 的分辨率的视频的话,是不支持 240 帧每秒的。

配置一个具体设备格式,你首先需要调用 lockForConfiguration: 来获取设备的配置属性的独占访问权限。接着你简单地使用 setActiveFormat: 来设置设备的捕获格式。这将会自动把 capture session 的预设设置为 AVCaptureSessionPresetInputPriority。

一旦你设置了预想的设备格式,你就可以在这种设备格式的约束参数范围内进行进一步的配置了。

对于视频捕获的对焦,曝光和白平衡的设置,与图像捕获时一样,具体可参考第 21 期“iOS 上的相机捕捉”。除了那些,这里还有一些视频特有的配置选项。

你可以用捕获设备的 activeVideoMinFrameDuration 和 activeVideoMaxFrameDuration 属性设置帧速率,一帧的时长是帧速率的倒数。设置帧速率之前,要先确认它是否在设备格式所支持的范围内,然后锁住捕获设备来进行配置。为了确保帧速率恒定,可以将最小与最大的帧时长设置成一样的值:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

NSError *error;

CMTime frameDuration = CMTimeMake(1, 60);

NSArray *supportedFrameRateRanges = [device.activeFormat videoSupportedFrameRateRanges];

BOOL frameRateSupported = NO;

for (AVFrameRateRange *range in supportedFrameRateRanges) {

    if (CMTIME_COMPARE_INLINE(frameDuration, >=, range.minFrameDuration) &&

        CMTIME_COMPARE_INLINE(frameDuration, <=, range.maxFrameDuration)) {

        frameRateSupported = YES;

    }

}

if (frameRateSupported && [device lockForConfiguration:&error]) {

    [device setActiveVideoMaxFrameDuration:frameDuration];

    [device setActiveVideoMinFrameDuration:frameDuration];

    [device unlockForConfiguration];

}

视频防抖 是在 iOS 6 和 iPhone 4S 发布时引入的功能。到了 iPhone 6,增加了更强劲和流畅的防抖模式,被称为影院级的视频防抖动。相关的 API 也有所改动 (目前为止并没有在文档中反映出来,不过可以查看头文件)。防抖并不是在捕获设备上配置的,而是在 AVCaptureConnection 上设置。由于不是所有的设备格式都支持全部的防抖模式,所以在实际应用中应事先确认具体的防抖模式是否支持:

1

2

3

4

5

6

AVCaptureDevice *device = ...;

AVCaptureConnection *connection = ...;

AVCaptureVideoStabilizationMode stabilizationMode = AVCaptureVideoStabilizationModeCinematic;

if ([device.activeFormat isVideoStabilizationModeSupported:stabilizationMode]) {

    [connection setPreferredVideoStabilizationMode:stabilizationMode];

}

iPhone 6 的另一个新特性就是视频 HDR (高动态范围图像),它是“高动态范围的视频流,与传统的将不同曝光度的静态图像合成成一张高动态范围图像的方法完全不同”,它是内建在传感器中的。有两种方法可以配置视频 HDR:直接将 capture device 的 videoHDREnabled 设置为启用或禁用,或者使用 automaticallyAdjustsVideoHDREnabled 属性来留给系统处理。

技术参考:iPhone 6 和 iPhone Plus 的新 AV Foundation 相机特性

  • 音频输入

之前展示的捕获设备列表里面只有一个音频设备,你可能觉得奇怪,毕竟 iPhone 6 有 3 个麦克风。然而因为有时会放在一起使用,便于优化性能,因此可能被当做一个设备来使用。例如在 iPhone 5 及以上的手机录制视频时,会同时使用前置和后置麦克风,用于定向降噪。

Technical Q&A: AVAudioSession – Microphone Selection

大多数情况下,设置成默认的麦克风配置即可。后置麦克风会自动搭配后置摄像头使用 (前置麦克风则用于降噪),前置麦克风和前置摄像头也是一样。

然而想要访问和配置单独的麦克风也是可行的。例如,当用户正在使用后置摄像头捕获场景的时候,使用前置麦克风来录制解说也应是可能的。这就要依赖于 AVAudioSession。 为了变更要访问的音频,audio session 首先需要设置为支持这样做的类别。然后我们需要遍历 audio session 的输入端口和端口数据来源,来找到我们想要的麦克风:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

// 配置 audio session

AVAudioSession *audioSession = [AVAudioSession sharedInstance];

[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

[audioSession setActive:YES error:nil];

// 寻找期望的输入端口

NSArray* inputs = [audioSession availableInputs];

AVAudioSessionPortDescription *builtInMic = nil;

for (AVAudioSessionPortDescription* port in inputs) {

    if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {

        builtInMic = port;

        break;

    }

}

// 寻找期望的麦克风

for (AVAudioSessionDataSourceDescription* source in builtInMic.dataSources) {

    if ([source.orientation isEqual:AVAudioSessionOrientationFront]) {

        [builtInMic setPreferredDataSource:source error:nil];

        [audioSession setPreferredInput:builtInMic error:&error];

        break;

    }

}

除了设置非默认的麦克风配置,你也可以使用 AVAudioSession 来配置其他音频设置,比如音频增益和采样率等。

  • 访问权限

有件事你需要记住,访问相机和麦克风需要先获得用户授权。当你给视频或音频创建第一个 AVCaptureDeviceInput 对象时,iOS 会自动弹出一次对话框,请求用户授权,但你最好还是自己实现下。之后你就可以在还没有被授权的时候,使用相同的代码来提示用户进行授权。当用户未授权时,对于录制视频或音频的尝试,得到的将是黑色画面和无声。

  • 输出

输入配置完了,现在把我们的注意力转向 capture session 的输出。

AVCaptureMovieFileOutput

将视频写入文件,最简单的选择就是使用 AVCaptureMovieFileOutput 对象。把它作为输出添加到 capture session 中,就可以将视频和音频写入 QuickTime 文件,这只需很少的配置。

1

2

3

4

5

6

7

AVCaptureMovieFileOutput *movieFileOutput = [AVCaptureMovieFileOutput new];

if([captureSession canAddOutput:movieFileOutput]){

    [captureSession addOutput:movieFileOutput];

}

// 开始录制

NSURL *outputURL = …

[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];

当实际的录制开始或停止时,想要接收回调的话就必须要一个录制代理。当录制停止时,输出通常还在写入数据,等它完成之后会调用代理方法。

AVCaptureMovieFileOutput 有一些其他的配置选项,比如在某段时间后,在达到某个指定的文件尺寸时,或者当设备的最小磁盘剩余空间达到某个阈值时停止录制。如果你还需要更多设置,比如自定义视频音频的压缩率,或者你想要在写入文件之前,处理视频音频的样本,那么你需要一些更复杂的操作。

AVCaptureDataOutput 和 AVAssetWriter

如果你想要对影音输出有更多的操作,你可以使用 AVCaptureVideoDataOutput 和 AVCaptureAudioDataOutput 而不是我们上节讨论的 AVCaptureMovieFileOutput。

这些输出将会各自捕获视频和音频的样本缓存,接着发送到它们的代理。代理要么对采样缓冲进行处理 (比如给视频加滤镜),要么保持原样传送。使用 AVAssetWriter 对象可以将样本缓存写入文件:

Using an AVAssetWriter

配置一个 asset writer 需要定义一个输出 URL 和文件格式,并添加一个或多个输入来接收采样的缓冲。我们还需要将输入的 expectsMediaInRealTime属性设置为 YES,因为它们需要从 capture session 实时获得数据。

1

2

3

4

5

6

7

8

9

10

11

12

NSURL *url = …;

AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeMPEG4 error:nil];

AVAssetWriterInput *videoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:nil];

videoInput.expectsMediaDataInRealTime = YES;

AVAssetWriterInput *audioInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:nil];

audioInput.expectsMediaDataInRealTime = YES;

if ([assetWriter canAddInput:videoInput]) {

    [assetWriter addInput:videoInput];

}

if ([assetWriter canAddInput:audioInput]) {

    [assetWriter addInput:audioInput];

}

(这里推荐将 asset writer 派送到后台串行队列中调用。)

在上面的示例代码中,我们将 asset writer 的 outputSettings 设置为 nil。这就意味着附加上来的样本不会再被重新编码。如果你确实想要重新编码这些样本,那么需要提供一个包含具体输出参数的字典。关于音频输出设置的键值被定义在这里, 关于视频输出设置的键值定义在这里。

为了更简单点,AVCaptureVideoDataOutput 和 AVCaptureAudioDataOutput 分别带有 recommendedVideoSettingsForAssetWriterWithOutputFileType: 和 recommendedAudioSettingsForAssetWriterWithOutputFileType: 方法,可以生成与 asset writer 兼容的带有全部键值对的字典。所以你可以通过在这个字典里调整你想要重写的属性,来简单地定义你自己的输出设置。比如,增加视频比特率来提高视频质量等。

或者,你也可以使用 AVOutputSettingsAssistant 来配置输出设置的字典,但是从我的经验来看,使用上面的方法会更好,它们会提供更实用的输出设置,比如视频比特率。另外,AVOutputSettingsAssistant 似乎存在一些缺点,例如,当你改变希望的视频的帧速率时,视频的比特率并不会改变。

实时预览

当使用 AVFoundation 来做图像捕获时,我们必须提供一套自定义的用户界面。其中一个关键的相机交互组件是实时预览图。最简单的实现方式是通过把 AVCaptureVideoPreviewLayer 对象作为一个 sublayer 加到相机图层上去:

1

2

3

4

5

AVCaptureSession *captureSession = ...;

AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];

UIView *cameraView = ...;

previewLayer.frame = cameraView.bounds;

[cameraView.layer addSublayer:previewLayer];

如果你想要更进一步操作,比如,在实时预览图加滤镜,你需要将 AVCaptureVideoDataOutput 对象加到 capture session,并且使用 OpenGL 展示画面,具体可查看该文“iOS 上的相机捕捉”

总结

有许多不同的方法可以给 iOS 上的视频捕获配置管线,从最直接的 UIImagePickerController,到精密配合的 AVCaptureSession 与 AVAssetWriter。如何抉择取决于你的项目要求,比如期望的视频质量和压缩率,或者是你想要展示给用户的相机控件。

© 著作权归作者所有

共有 人打赏支持
天机
粉丝 1
博文 24
码字总数 0
作品 0
部门经理
iOS新特性框架、仿微信图片浏览、视频监控、爱心动画、文字适配等源码

iOS精选源码 iOS一个看电影、电视剧集合 HDCinema(http://www.code4app.com/thread-29425-1-1.html) 一个非常简易的新特性集成框架NewFeatures(http://www.code4app.com/thread-29433-1-1.ht......

sunnyaigd ⋅ 05/02 ⋅ 0

开发微信H5视频秀项目遇到的坑

介绍 手头上正好有个项目,需要做一个微信端H5视频秀的一个项目,想想好像挺简单的,由两个视频组成,播放完第一个视频后点击按钮继而播放第二个视频。好了,结果微信的坑TM的多 问题排查 自...

🚲Allen ⋅ 05/18 ⋅ 0

ZipperDown漏洞来了!微博、陌陌、快手等常用 iOS 应用恐要中招

雷锋网(公众号:雷锋网)消息,5月15日,盘古实验室对外宣布,他们在针对不同客户的 iOS 应用安全审计过程中,发现了一类通用的安全漏洞---ZipperDown漏洞。 10%的iOS应用可能受ZipperDow...

郭佳 ⋅ 05/15 ⋅ 0

iOS小白点效果、打地鼠游戏、轮播效果、画板、富文本编辑器等源码

iOS精选源码 美团外卖商家点菜页面(http://www.code4app.com/thread-29383-1-1.html) 板书录制演示程序(http://www.code4app.com/thread-29384-1-1.html) 分类轮播、直播间礼物列表轮播 -- O...

sunnyaigd ⋅ 04/24 ⋅ 0

iOS源码补完计划--AFNetworking 3.1.0源码研读

参拜一下AFNetworking的源码。 第四篇源码、暂时来看也是iOS方向的最后一篇、撸完准备趁着热乎撸一撸网络协议。 目录 准备工作 功能模块 AFURLSessionManager/AFHTTPSessionManager AFNetwo...

kirito_song ⋅ 05/25 ⋅ 0

Macaca App inspector

为方便更多用户查找界面元素,提供了同时支持 Android 和 iOS 平台的 Inspector 工具,此功能也是 Macaca 录制器的重要部分。另外,Web 元素查找请直接只用 。 Android iOS 安装 用法 更多用...

awesome@qa ⋅ 05/16 ⋅ 0

iOS Animation创建及使用

iOS 实现的基本动画 头尾式动画 2.block动画的方法 iOS显示关键帧动画 关键帧动画 动画的创建和使用 第一种:UIView 代码块调用 第二种:UIView [begin commit]模式 第三种:使用Core Animat...

奋拓达 ⋅ 05/23 ⋅ 0

zymedia的在使用中碰到的问题

记笔记,免忘记!最近用到了视频插件zyMedia。这个插件的简介地址:https://github.com/ireaderlab/zyMedia 问题一: 首先视频的上方显示的标题,实例是这样写的data-config='{"mediaTitle":...

zilvzsy ⋅ 05/12 ⋅ 0

人工智能要成精了?英伟达展示逆天修图技术

人工智能要成精了?英伟达展示逆天修图技术 2018-04-25 12:03编辑: 枣泥布丁分类:AI来源:青亭网 英伟达人工智能PS 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发工程师 京东招聘...

枣泥布丁 ⋅ 04/25 ⋅ 0

一样的iOS开发程序员为什么有人4k有人40k?

前言 移动开发真正火起来其实就是最近这几年,iOS 开发技术因为发展也就才这么几年,所以值得做的事情还有很多,这就造成了每年苹果的 WWDC 都会推出一堆新的特性和 API。整体上来说,这对业...

原来是泽镜啊 ⋅ 05/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java Web如何操作Cookie的添加修改和删除

创建Cookie对象 Cookie cookie = new Cookie("id", "1"); 修改Cookie值 cookie.setValue("2"); 设置Cookie有效期和删除Cookie cookie.setMaxAge(24*60*60); // Cookie有效时间 co......

二营长意大利炮 ⋅ 今天 ⋅ 0

【每天一个JQuery特效】淡入淡出显示或隐藏窗口

我是JQuery新手爱好者,有时间就练练代码,防止手生,争取每天一个JQuery练习,在这个博客记录下学习的笔记。 本特效主要采用fadeIn()和fadeOut()方法显示淡入淡出的显示效果显示或隐藏元...

Rhymo-Wu ⋅ 今天 ⋅ 0

Spring JDBC使用方法

普通实现: 1、创建数据表customer。 可以使用任何数据库实现,在项目中要引入相应数据库驱动包并配置相应数据库连接。 2、创建Customer pojo。 Customer类的属性对应数据库的属性,除了为每...

霍淇滨 ⋅ 今天 ⋅ 0

Contos 7 安装Jenkins

Jenkins是一款能提高效率的软件,它能帮你把软件开发过程形成工作流,典型的工作流包括以下几个步骤 开发 提交 编译 测试 发布 有了Jenkins的帮助,在这5步中,除了第1步,后续的4步都是自动...

欧虞山 ⋅ 今天 ⋅ 0

revel

revel install go get github.com/revel/revelgo get github.com/revel/cmd create new app revel new git.oschina.net/zdglf/myapp run app revel run git.oschina.net/zdglf/myapp ot......

zdglf ⋅ 今天 ⋅ 0

49. Group Anagrams - LeetCode

Question 49. Group Anagrams Solution 思路:维护一个map,key是输入数组中的字符串(根据字符排好序) Java实现: public List<List<String>> groupAnagrams(String[] strs) { Map<Strin......

yysue ⋅ 今天 ⋅ 0

spring Email

使用spring发Email其实就是使用spring自己封装携带的一个javamail.JavaMailSenderImpl类而已。这个类可以当一个普通的java对象来使用,也可以通过把它配置变成spring Bean的方式然后注入使用...

BobwithB ⋅ 今天 ⋅ 0

spark 整理的一些知识

Spark 知识点 请描述spark RDD原理与特征? RDD全称是resilient distributed dataset(具有弹性的分布式数据集)。一个RDD仅仅是一个分布式的元素集合。在Spark中,所有工作都表示为创建新的...

tuoleisi77 ⋅ 今天 ⋅ 0

思考

时间一天天过感觉自己有在成长吗?最怕的是时光匆匆而过,自己没有收获!下面总结下最近自己的思考。 认识自己 认识另一个自己,人们常说要虚心听取别人意见和建议。然而人往往是很难做到的,...

hello_hp ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部