アプリなどを開発するブログ

React Native / Swift / Ruby on Railsなどの学習メモ。


iOSでストリーミング再生中の動画キャプチャを撮りたいが方法がない

やりたいこと

サーバー上にあるm3u8ファイルをiPhoneアプリでストリーミング再生してる。
ボタンを押すと今映ってる映像の写真を撮ってローカルに保存したい。
一見、以下のような処理で簡単に取得できそうである。

let rect = view.bounds

UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
let context: CGContextRef = UIGraphicsGetCurrentContext()
view.layer.renderInContext(context)
let capturedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

が、真っ黒な画像が出力されるだけ。

色々調べたけど

stackoverflow.com

色々試したけどできないっぽいよという回答。

stackoverflow.com

A) UIGetScreenImage() という非公開メソッドで撮れるけど、リジェクトの可能性もあるよ
B) AVPlayerLayerで再生して、AVAssetImageGenerator の copyCGImageAtTime で撮れるよ
  -> ただしこれは、サーバー上の動画ファイルには使えないみたい

stackoverflow.com ここに載ってる方法でやってみたけど、imageRefが取得できない。
「できた!」って言ってる人は多分ローカルの動画ファイルでやってる気がする。

var url = NSURL(string: Constants.streamUrls[0])
if var asset = AVAsset.assetWithURL(url) as? AVAsset {
    var imageGenerator:AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
    var time = CMTimeMake(1, 1)
    var imageRef = imageGenerator.copyCGImageAtTime(time, actualTime: nil, error: nil)
    var thumbnail = UIImage(CGImage: imageRef)
    return thumbnail!
}        

以下のようなエラーを吐いてしまう。

Optional(Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x17046c140 {NSUnderlyingError=0x174243840 "The operation couldn’t be completed. (OSStatus error -12782.)", NSLocalizedFailureReason=An unknown error occurred (-12782), NSLocalizedDescription=The operation could not be completed})

stackoverflow.com こちらもうまくいかない。

AVAssetImageGeneratorを使っての取得も試みたが、ダメだった。
恐らくこちらも有効なのはローカルのビデオのみで、リモートの動画はだめくさい?

func captureFromPlayer(player: AVPlayer, maxSize: CGSize) -> UIImage? {
        var actualTime: CMTime = CMTimeMake(0, 0)
        var error: NSError?
        
        var generator: AVAssetImageGenerator = AVAssetImageGenerator(asset: player.currentItem.asset)
        
        generator.maximumSize = maxSize
        
        println("player.currentTime() :\(player.currentTime())")

        
        var cgIm: CGImageRef = generator.copyCGImageAtTime(player.currentTime(), actualTime: &actualTime, error: &error)
        var image = UIImage(CGImage: cgIm)
        if error != nil {
            println("erorr : \(error?.localizedDescription)")
            println("CMTimeGetSeconds : \(CMTimeGetSeconds(actualTime))")
            if let current = streamView.player?.currentTime() {
                CMTimeGetSeconds(current)
            }
            
            return nil
        }
        return image
    }
    

こっちもやってみたけど、そもそもtracksが空。

func setupReader() {
        let url = NSURL(string: urlString)
        let asset:AVURLAsset = AVURLAsset(URL: url, options: nil)
        asset.loadValuesAsynchronouslyForKeys(["tracks"], completionHandler: {
            dispatch_sync(dispatch_get_main_queue(), { () -> () in
                var videoTrack: AVAssetTrack? = nil
                var tracks = asset.tracksWithMediaType(AVMediaTypeVideo)
                if tracks.count == 1 {
                    if let track = tracks[0] as? AVAssetTrack {
                        var error: NSError?
                        self.movieReader = AVAssetReader(asset: asset, error: &error)
                        if error != nil {
                            println("error: \(error)")
                        }
                        
                        var key:String = kCVPixelBufferPixelFormatTypeKey as String
                        var value:Int = kCVPixelFormatType_4444AYpCbCr16 as Int
                        var videoSettings = [key: value]
                        
                        
                        self.movieReader?.addOutput(AVAssetReaderTrackOutput(track: videoTrack, outputSettings: videoSettings))
                        self.movieReader?.startReading()
                    }
                }
            })
        })
    }

iOS7から実装されたスナップショットを撮るメソッドを試す

こんなんあったんですね。

let capture: UIView = view.snapshotViewAfterScreenUpdates(true)

スクリーン自体のスナップショットを撮影するメソッドも、UIScreenに実装されている。

let capture = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(true)

だがこれも、UIViewをUIImageに変換するこちらのお決まりのメソッドに投げると、
AVPlayerLayerの所だけが真っ黒になって返ってくる。

func viewToImage(capturedView:UIView) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(capturedView.bounds.size, capturedView.opaque, 0.0)
        capturedView.layer.renderInContext(UIGraphicsGetCurrentContext())
        var img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img
    }

ちなみに、キャプチャのUIView自体は、ビデオの動画もバッチリ表示されている。
UIImageにする段階で、ビデオ動画がすっぽり抜け落ちる。

なんでや!なんでなんや!
うーむ。。

こんなのもあった

stackoverflow.com

これもだめだった

func snapByOpenGL() -> UIImage {
        if let time = streamView.playerItem?.currentTime() {
            if var pixelBuffer: CVPixelBufferRef = streamView.output?.copyPixelBufferForItemTime(time, itemTimeForDisplay: nil) {
                var ciImage = CIImage(CVPixelBuffer: pixelBuffer)
                
                var temporaryContext: CIContext = CIContext(options: nil)
                var rect = CGRectMake(0, 0, CGFloat(CVPixelBufferGetWidth(pixelBuffer)), CGFloat(CVPixelBufferGetHeight(pixelBuffer)))


                var videoImage: CGImageRef = temporaryContext.createCGImage(ciImage, fromRect: rect)
                var image = UIImage(CGImage: videoImage)
                return image!
            }
        }
        
        return UIImage()
    }

Instagramのハッシュタグつけたのに投稿が表示されない問題

f:id:device_me:20150822174427j:plain

今日(2015年8月22日)、Instagram の投稿にハッシュタグが反映されなくてすごく困った。
同じような現象が起こった時に誰かの役に立てばと思い、どんな事が起こったかまとめておく。

正確には以下の状態だった。

#サンプルハッシュタグ • Instagram photos and videos

解決方法をググって以下を試してみた。

【解決方法1】プライベートモードを解除する

よくある話だが、自分のInstagramアカウントがプライベートモードになってて、 ハッシュタグ投稿一覧ページに反映されないパターン。
Instagramアプリの設定から、プライベートモードをOFFにすれば、即時反映されるようになる。

【解決方法2】「禁止ハッシュタグ」を投稿から削除する

インスタグラムには「バンされたハッシュタグ」が存在する。
エッチなものやスパム目的の投稿をはじくためや、
「photography」など抽象的過ぎるハッシュタグを禁止することで、写真を探しやすくするため、
という意図があるらしい。

ちなみにバンされたハッシュタグ一覧は以下

hype.my

バンされたハッシュタグをつけた投稿は、他のハッシュタグ検索にも引っかからなくなる。
なので、バンされたハッシュタグをコメント欄から削除すれば、検索にひっかかるようになる。


【2】は今回初めて知ったが、他にハッシュタグを一切つけない状態でも投稿が正常に表示されない。。。
もしかして、この数日の間にスパム対策のためにInstagramに仕様変更があり、
全てのハッシュタグをデフォルトでバンし、
そのハッシュタグのついた投稿数が一定数になるまでバンされた状態になる、みたいな事になってるのか?
と思ってひたすら投稿したりいいねを押したりしていた。

【結論】Instagramの一時的なバグか

諦めかけた頃、突然ハッシュタグが反映されるようになった。
理由はわからないが、単なるインスタグラムのバグだったようだ。。
今日の朝にバグが発動し、16時頃修正された。

Twittergoogle の24時間以内検索をやってみると、以下のような投稿がひっかかった。
探してもこれくらいしか出てこなかったので、みんなあんまり困ってなかったのかな?

ともあれ、問題が解決して一件落着。よかったよかった。

answers.yahoo.com

新しいChromeで0.0.0.0:* にアクセスできない

いつからか、chromeのアドレスバーで0.0.0.0を入力してエンターを押すと、
0.0.0.0 という単語にアクセスしてしまうようになってしまいました。何で?

とりあえずhttp://localhost:* でアクセスするようにしましたが、
設定で変えることができるのでしょうか?
ご存知のかた、いらっしゃいましたら教えていただけると幸いです。

Node.jsで動画書出し

Video convert to WebM

http://www.sysord.fr/Sysord/ressource_whammy.jsf

Weppyを使ったwebm生成ライブラリ

https://github.com/antimatter15/whammy

Node.js & real-time video encoding

http://blog.romanliutikov.com/post/76000554454/node-js-real-time-video-encoding

Redisのコマンドメモ

redisサーバーの起動/終了

# サーバーの起動  
$ redis-server  

# サーバーの停止  
CTRL + C

redisクライアント

# クライアントの起動  
$ redis-cli 

# クライアントの停止
$ exit

# クライアントからサーバーを停止  
$ shutdown
# DBを選択  
# <数値>番目のDBを選択する。デフォルトは0。  
$ select <数値>

# バックグラウンとで保存(永続化)
$ bgsave

なお、データベースファイルの保存先はredisを立ち上げたディレクトリ。
拡張子は.rdb

フリーランス爆速スターターキットを作りたい

先日からフリーランスになった。
まだ事業開業届けも出していなければ、保険証も会社に返却して持ってない状態。
とりあえずお金の事は全部クラウド会計ソフトfreee にお任せすることにしたが、
今後のプランを組み立てるにあたって、稼ぐ額の目標を月いくらに設定すべきかもよくわかってない。
というのも、収入に対してのかかってくる税金がどれくらいなのか、まだ詳しくわかっていないのだ。

色々わからないことが多すぎて、開業する人はみんなこの道を通るのかと思ったら、
まとめて全部面倒見てくれるサービスがあったらいいのにと思った。
ので、サービス化するために自分が不便に思った点をまとめていく。

月どれくらい稼ぐと、どれくらい税金や健康保険で持っていかれるのか

税金シュミレーターとかネットにぼちぼち転がってはいるが、使いにくい。
以下を満たすようなシミュレーターがあるといい。

  • 売上を入力すると様々な税金を差し引いたいわゆる「手取り額」がわかる
  • どの項目が何のためのものなのかが一発でわかる
  • 税率が変わるしきい値はどこかが一発でわかる
  • 金額を入力するとその場で税金の数値もサクサク変わって、色々シミュレーションできる

健康保険

単純に計算したら年間で50万近く国民保険に支払う計算になった。マジか...
デザイナーなら文美国保というのに入れば安く済むみたい。
自分はデザインもやってるのでこれに入ろうと思う。
こういう情報もどこかにまとまっていればいいのに。

文芸美術国民健康保険組合 itereta.hatenablog.com

経費について

これは必要経費になるのか?みたいな話、検索すると色々出てくるけど、
体系的に見やすくまとめたサイトがあってもいいかなと思う。

今のところざっとこんな感じだ。
また欲しいものがあったらまとめていきたい。

WebSocket-Rails の記事まとめ

WebSocketを使ってリアルタイムなアプリが作りたいと思って、色々調べております。 github.com

Twitter Streaming APIからツイート受け取ってPUSH通知するアプリをHerokuに

qiita.com

github.com

altarf.net

ithijikata.hatenablog.com

washiiku.hatenablog.com

ブラウザから位置情報を取得し別端末にPUSH通知を送るWEBアプリ

dev.classmethod.jp

dev.classmethod.jp

blog.interfirm.co.jp

コラム - Ruby & Rails | 第14回 WebSocketでサーバプッシュ その3 ~Websocket-Rails~|CTC教育サービス 研修/トレーニング

代替 : EM-WebSocket

コラム - Ruby & Rails | 第13回 WebSocketでサーバプッシュ その2 〜EM-WebSocket〜|CTC教育サービス 研修/トレーニング

www.techscore.com

sinatraでやるなら

Ruby製WebSocketアプリを最速でHerokuにデプロイする5つのステップ

knockout.jsとの連携

qiita.com